I'm using a jQuery UI based dateRangePicker which I am trying to bind with a KnockoutJS based viewModel via a custom binder. But I am not even able to make the dateRangePicker read an observable like
this.range = ko.observable("Jul 1,2015 - Jul 3,2015");
Here is my JSFiddle attempt. Is that a wrong approach and do I need create something like this
this.startDate
this.endDate
The dateRangePicker documentation states that it stores an object with the following properties: start and end. It stores this as a JSON string in the value field of the <input> element that is used to contain dateRangePicker. Therefore, you probably want your range observable to also store an object with start and end properties. I wrote a custom binding which will apply the dateRangePicker to an element and will write the object into your observable any time a different selection is made:
ko.bindingHandlers.dateRangePicker = {
init: function(element, valueAccessor, allBindings, viewModel, bindingContext) {
var $el = $(element);
$el.daterangepicker({
onChange: function() {
var range = JSON.parse($el.val());
valueAccessor()(range);
}
});
var value = valueAccessor()();
if (value) {
var range = {"start": new Date(value["start"] + " 00:00:00")};
if (value["end"]) {
range["end"] = new Date(value["end"] + " 00:00:00");
}
$el.daterangepicker("setRange", range);
}
}
};
You can then apply this to your <input> element:
<input id="e1" data-bind="dateRangePicker: range">
If you need to initialize the value on the dateRangePicker through the viewmodel, then you need to store an object into the range observable that matches the format that the dateRangePicker uses:
this.range = ko.observable({start:"2015-07-01", end:"2015-07-03"});
Here is a fiddle: http://jsfiddle.net/efywmomz/
Update
I altered the custom binding to use the moment library and updated the fiddle to initialize the range from the viewmodel: http://jsfiddle.net/efywmomz/1/
ko.bindingHandlers.dateRangePicker = {
init: function(element, valueAccessor, allBindings, viewModel, bindingContext) {
var $el = $(element);
$el.daterangepicker({
onChange: function() {
var range = JSON.parse($el.val());
valueAccessor()(range);
}
});
var value = valueAccessor()();
if (value) {
var range = {"start": moment(value["start"])._d};
if (value["end"]) {
range["end"] = moment(value["end"])._d;
}
$el.daterangepicker("setRange", range);
}
}
};
Here is a sample which i've implemented with moment js library and daterangepicker js library with knockout
HTML
<div id="reportrange" class="pull-right" data-bind="BindRangeDatePicker: Value">
<i class="fa fa-calendar fa-lg"></i>
<input type="text" data-bind="value: Value" readonly />
<span data-bind="text: Value"></span><b class="caret"></b>
</div>
knockout
ko.bindingHandlers.BindRangeDatePicker = {
init: function (element, valueAccessor, allBindings, vm, context) {
$(element).daterangepicker(
{
ranges: {
'Today': [moment(), moment()],
'Yesterday': [moment().subtract('days', 1), moment().subtract('days', 1)],
'Last 7 Days': [moment().subtract('days', 6), moment()],
'Last 30 Days': [moment().subtract('days', 29), moment()],
'This Month': [moment().startOf('month'), moment().endOf('month')],
'Last Month': [moment().subtract('month', 1).startOf('month'), moment().subtract('month', 1).endOf('month')]
},
startDate: moment().subtract('days', 29),
endDate: moment()
}, function (start, end) {
$(element).find('span').html(start.format('MMMM D, YYYY') + ' - ' + end.format('MMMM D, YYYY'));
}
);
},
update: function (element, valueAccessor, allBindings, vm, context) {
var value = valueAccessor();
$(element).daterangepicker(
{
ranges: {
'Today': [moment(), moment()],
'Yesterday': [moment().subtract('days', 1), moment().subtract('days', 1)],
'Last 7 Days': [moment().subtract('days', 6), moment()],
'Last 30 Days': [moment().subtract('days', 29), moment()],
'This Month': [moment().startOf('month'), moment().endOf('month')],
'Last Month': [moment().subtract('month', 1).startOf('month'), moment().subtract('month', 1).endOf('month')]
},
startDate: moment().subtract('days', 29),
endDate: moment()
}, function (start, end) {
//var val = start.format('MMMM D, YYYY') + ' - ' + end.format('MMMM D, YYYY');
//valueAccessor(val.toString());
$(element).find('span').html(start.format('MMMM D, YYYY') + ' - ' + end.format('MMMM D, YYYY'));
}
);
}
}
Related
I am using bootstrap dual listbox pluging in my ASP.NET MVC project.
I am also using Knockout in the project. I am trying to create bindingHandler for the this plugin to make it working smoothly with knockout.
here is what I tried
Binding Handler
ko.bindingHandlers.dualList = {
init: function (element, valueAccessor) {
$(element).bootstrapDualListbox({
selectorMinimalHeight: 160
});
$(element).on('change', function () {
$(element).bootstrapDualListbox('refresh', true);
});
ko.utils.domNodeDisposal.addDisposeCallback(element, function () {
$(element).bootstrapDualListbox('destroy');
});
},
update: function (element, valueAccessor) {
$(element).bootstrapDualListbox('refresh', true);
}
}
HTML
<select class="form-control" data-bind="foreach:{data: EditedElement().Operations, as : 'op'} , dualList: EditedElement().Operations" multiple>
<option data-bind="value: op.OperationID(), text: op.Name(), selected: op.IsSelected()"></option>
</select>
View Model
function SelectOperationVM(operationId, isSelected, name) {
var self = this;
self.OperationID = ko.observable(operationId);
self.IsSelected = ko.observable(isSelected);
self.Name = ko.observable(name);
self.copy = function () {
return new SelectOperationVM(self.OperationID(), self.IsSelected(), self.Name());
}
}
My problem is that I can not make sync between the viewModel observableArray, and the plugin.
In other words, I want the changes in the plugin (the user removed some options or added some options) to be reflected on the view model property, and vice verse
to sync, you need to pass multiple observables to custom binding
so your html should be like
<select class="form-control" data-bind="foreach: { data: Operations, as: 'op'}, dualList: { options: Operations, selected: Selected }" multiple>
<option data-bind="value: op.OperationID(), text: op.Name(), selected: op.IsSelected()"></option>
</select>
and custom binding be like
ko.bindingHandlers.dualList = {
init: function(element, valueAccessor) {
var data = ko.utils.unwrapObservable(valueAccessor());
$(element).bootstrapDualListbox({
selectorMinimalHeight: 160
});
$(element).on('change', function() {
// save selected to an observable
data.selected($(element).val());;
});
ko.utils.domNodeDisposal.addDisposeCallback(element, function() {
$(element).bootstrapDualListbox('destroy');
});
},
update: function(element, valueAccessor) {
// to view if there is an update (without this "update" will not fire)
var options = ko.utils.unwrapObservable(valueAccessor()).options();
$(element).bootstrapDualListbox('refresh', true);
}
}
also i have created a dirty working jsfiddle
This fiddle shows how to bind a jQuery slider 'slide' event to a Knockout observable. How would this need to change to also bind the 'max' option of the slider to an observable? Do you have to create an entirely new ko.bindingsHandler entry? Or can the existing one be used?
Here is the code from the fiddle for reference.
HTML
<h2>Slider Demo</h2>
Savings: <input data-bind="value: savings, valueUpdate: 'afterkeydown'" />
<div style="margin: 10px" data-bind="slider: savings, sliderOptions: {min: 0, max: 100, range: 'min', step: 1}"></div>
Spent: <input data-bind="value: spent, valueUpdate: 'afterkeydown'" />
<div style="margin: 10px" data-bind="slider: spent, sliderOptions: {min: 0, max: 100, range: 'min', step: 1}"></div>
Net: <span data-bind="text: net"></span>
JS
ko.bindingHandlers.slider = {
init: function (element, valueAccessor, allBindingsAccessor) {
var options = allBindingsAccessor().sliderOptions || {};
$(element).slider(options);
ko.utils.registerEventHandler(element, "slidechange", function (event, ui) {
var observable = valueAccessor();
observable(ui.value);
});
ko.utils.domNodeDisposal.addDisposeCallback(element, function () {
$(element).slider("destroy");
});
ko.utils.registerEventHandler(element, "slide", function (event, ui) {
var observable = valueAccessor();
observable(ui.value);
});
},
update: function (element, valueAccessor) {
var value = ko.utils.unwrapObservable(valueAccessor());
if (isNaN(value)) value = 0;
$(element).slider("value", value);
}
};
var ViewModel = function() {
var self = this;
self.savings = ko.observable(10);
self.spent = ko.observable(5);
self.net = ko.computed(function() {
return self.savings() - self.spent();
});
}
ko.applyBindings(new ViewModel());
Look at this fiddle. I added checking if max is observable and subscribing to it:
if (ko.isObservable(options.max)) {
options.max.subscribe(function(newValue) {
$(element).slider('option', 'max', newValue);
});
options.max = ko.utils.unwrapObservable(options.max);
}
I have a collection of jQUery Ui bindings for KO. I havent done the slider because I havent needed that control in a project. But check my button binding
https://github.com/AndersMalmgren/Knockout.Bindings
ko.bindingHandlers.button = {
initIcon: function (options) {
if (options.icon) {
options.icons = { primary: options.icon };
}
},
init: function (element, valueAccessor) {
var options = ko.utils.unwrapObservable(ko.toJS(valueAccessor())) || {};
ko.bindingHandlers.button.initIcon(options);
ko.utils.domNodeDisposal.addDisposeCallback(element, function () {
$(element).button("destroy");
});
$(element).button(options);
},
update: function (element, valueAccessor) {
var options = ko.toJS(valueAccessor());
ko.bindingHandlers.button.initIcon(options);
if (options) {
$(element).button(options);
}
}
};
The magic is done in the update function, KO will by default subscribe to all observables in a object literal, so if you bind to { max: aObservable } the update function will trigger when any child updates.
I then do ko.toJS(valueAccessor()); to un observify the object and use that to update the jQuery control. This method can be used for slider as well, its generic and you do not need to add extra code for each setting
I've got a view model that looks like this:
var ViewModel = function() {
var self = this;
self.hourOptions = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23];
self.minuteOptions = [0, 15, 30, 45];
self.formatTimeOption = function(hour) {
if (hour < 10) return "0" + hour;
return hour.toString();
};
self.startDate = ko.observable(null);
self.startDateHour = ko.computed({
read: function() {
return new Date(self.startDate()).getHours();
},
write: function(value) {
var newDate = new Date(self.startDate());
newDate.setHours(value);
self.startDate(newDate);
}
});
self.startDateMinute = ko.computed({
read: function() {
return new Date(self.startDate()).getMinutes();
},
write: function(value) {
var newDate = new Date(self.startDate());
newDate.setMinutes(value);
self.startDate(newDate);
}
});
};
As you can see, I've got a writeable computed observable that updates the startDate hours / minutes when updated.
This is working, however when it does so, the datepicker input field displays the long form of the date, rather than (for example)
01/03/2013
JSFiddle of this is available here: http://jsfiddle.net/alexjamesbrown/2kSpL/9/
I solved this by adding the following custom binding handler, as taken from this answer
ko.bindingHandlers.datepicker = {
init: function(element, valueAccessor, allBindingsAccessor) {
//initialize datepicker with some optional options
var options = allBindingsAccessor().datepickerOptions || {};
$(element).datepicker(options);
//handle the field changing
ko.utils.registerEventHandler(element, "change", function() {
var observable = valueAccessor();
observable($(element).datepicker("getDate"));
});
//handle disposal (if KO removes by the template binding)
ko.utils.domNodeDisposal.addDisposeCallback(element, function() {
$(element).datepicker("destroy");
});
},
update: function(element, valueAccessor) {
var value = ko.utils.unwrapObservable(valueAccessor()),
current = $(element).datepicker("getDate");
if (value - current !== 0) {
$(element).datepicker("setDate", value);
}
}
};
Here's a working JSFiddle:
http://jsfiddle.net/alexjamesbrown/v6hdS/
I'm trying to figure out if knockout js would work nicely for the following problem:
I have multiple sliders that I want to link to textboxes.
When the textbox is changed the corresponding slider must update to the new value and vice versa.
On changing the slider value or textbox a function needs to be called that uses the input from all textboxes to calculate a result.
I have my quick and dirty jQuery solution here.
Would it be easy to achieve the same result in a more elegant way using knockout js?
I guess I would need to create a custom binding handler like its done in jQuery UI datepicker change event not caught by KnockoutJS
Here is an example: http://jsfiddle.net/jearles/Dt7Ka/
I use a custom binding to integrate the jquery-ui slider and use Knockout to capture the inputs and calculate the net amount.
--
UI
<h2>Slider Demo</h2>
Savings: <input data-bind="value: savings, valueUpdate: 'afterkeydown'" />
<div style="margin: 10px" data-bind="slider: savings, sliderOptions: {min: 0, max: 100, range: 'min', step: 1}"></div>
Spent: <input data-bind="value: spent, valueUpdate: 'afterkeydown'" />
<div style="margin: 10px" data-bind="slider: spent, sliderOptions: {min: 0, max: 100, range: 'min', step: 1}"></div>
Net: <span data-bind="text: net"></span>
View Model
ko.bindingHandlers.slider = {
init: function (element, valueAccessor, allBindingsAccessor) {
var options = allBindingsAccessor().sliderOptions || {};
$(element).slider(options);
$(element).slider({
"slide": function (event, ui) {
var observable = valueAccessor();
observable(ui.value);
},
"change": function (event, ui) {
var observable = valueAccessor();
observable(ui.value);
}
});
ko.utils.domNodeDisposal.addDisposeCallback(element, function () {
$(element).slider("destroy");
});
},
update: function (element, valueAccessor) {
var value = ko.unwrap(valueAccessor());
if (isNaN(value)) {
value = 0;
}
$(element).slider("value", value);
}
};
var ViewModel = function() {
var self = this;
self.savings = ko.observable(10);
self.spent = ko.observable(5);
self.net = ko.computed(function() {
return self.savings() - self.spent();
});
}
ko.applyBindings(new ViewModel());
I know it's some days ago but I made a few adjustments to John Earles code:
ko.bindingHandlers.slider = {
init: function (element, valueAccessor, allBindingsAccessor) {
var options = allBindingsAccessor().sliderOptions || {};
$(element).slider(options);
ko.utils.registerEventHandler(element, "slidechange", function (event, ui) {
var observable = valueAccessor();
observable(ui.value);
});
ko.utils.domNodeDisposal.addDisposeCallback(element, function () {
$(element).slider("destroy");
});
ko.utils.registerEventHandler(element, "slide", function (event, ui) {
var observable = valueAccessor();
observable(ui.value);
});
},
update: function (element, valueAccessor, allBindingsAccessor) {
var value = ko.utils.unwrapObservable(valueAccessor());
if (isNaN(value)) value = 0;
$(element).slider("option", allBindingsAccessor().sliderOptions);
$(element).slider("value", value);
}
};
The reason for this is that if you use options that change (fx another observable) then it won't affect the slider even if you wanted it to do so.
#John Earles and #Michael Kire Hansen: thanks for your wonderful solutions!
I used the advanced code from Michael Kire Hansen. I tied the "max:" option of the slider to a ko.observable and it turned out that the slider does not correctly update the value in this case. Example: Lets say the slider is at value 25 of max 25 und you change the max value to 100, the slider stays at the most right position, indicating that it is at the max value (but value is still 25, not 100). As soon as you slide one point to the left, you get the value updated to 99.
Solution:
in the "update:" part just switch the last two lines to:
$(element).slider("option", allBindingsAccessor().sliderOptions);
$(element).slider("value", value);
This changes the options first, then the value and it works like a charm.
Thanks so much for the help, I needed to use a range slider in my scenario so here is an extension to #John Earles and #Michael Kire Hansen
ko.bindingHandlers.sliderRange = {
init: function (element, valueAccessor, allBindingsAccessor) {
var options = allBindingsAccessor().sliderOptions || {};
$(element).slider(options);
ko.utils.registerEventHandler(element, "slidechange", function (event, ui) {
var observable = valueAccessor();
observable.Min(ui.values[0]);
observable.Max(ui.values[1]);
});
ko.utils.domNodeDisposal.addDisposeCallback(element, function () {
$(element).slider("destroy");
});
ko.utils.registerEventHandler(element, "slide", function (event, ui) {
var observable = valueAccessor();
observable.Min(ui.values[0]);
observable.Max(ui.values[1]);
});
},
update: function (element, valueAccessor, allBindingsAccessor) {
var value = ko.utils.unwrapObservable(valueAccessor());
if (isNaN(value.Min())) value.Min(0);
if (isNaN(value.Max())) value.Max(0);
$(element).slider("option", allBindingsAccessor().sliderOptions);
$(element).slider("values", 0, value.Min());
$(element).slider("values", 1, value.Max());
}
};
and then the HTML to accompany it
<div id="slider-range"
data-bind="sliderRange: { Min: 0, Max: 100 },
sliderOptions: {
range: true,
min: 0,
max: 100,
step: 10,
values: [0, 100]
}"></div>
I am currently porting a large application over to a HTML5 based web app - I have started building the app in AngularJS and enjoying the power of the AngularJS framework - I have one issue standing in my way currently:
I have a directive that gives me a jQuery Datepicker however the binding to the model does not seem to be working.
http://jsfiddle.net/9BRNf/
I am probably misunderstanding the way directives work and would like to see if I can patch this part of my understanding of the framework. I have gone through loads of examples (including the angularui project on github but still not making sense of why the binding is not happening)
any assistance will be greatly appreciated.
For those Googling this issue (as I was), a simpler way of tying in the jQuery UI datepicker with Angular is to do this...
$.datepicker.setDefaults({
// When a date is selected from the picker
onSelect: function(newValue) {
if (window.angular && angular.element)
// Update the angular model
angular.element(this).controller("ngModel").$setViewValue(newValue);
}
});
Just place it prior to your .datepicker() initialisation code.
(Taken from another answer I posted here: https://stackoverflow.com/a/17206242/195835)
First off, it's great that you are using angularjs, its a sweet framework. An offshoot project was started awhile back to deal with things like wrapping jquery-ui and creating ui modules.
Below is link to Peter Bacon Darwin's implementation.
https://github.com/angular-ui/angular-ui/tree/master/modules/directives/date
--dan
The angular-ui datepicker wasn't working with Angular 1.0.0, so I rewrote it. My fork gives you the ability to set how the date is formatted inside the input and how it gets saved back to the model.
Code: https://gist.github.com/2967979
jsFiddle: http://jsfiddle.net/m8L8Y/8/ (It's missing jquery-ui styles but works just the same)
// Code inspired by angular-ui https://github.com/angular-ui/angular-ui/blob/master/modules/directives/date/src/date.js
/*
Features:
* via the ui-date attribute:
* Ability to say how model is parsed into a date object
* Ability to say how input's value is parsed into a date object
* Ability to say how a date object is saved to the model
* Ability to say how a date object is displayed in the input
* via the ui-date-picker attribute
* Ability to directly configure the jQuery-ui datepicker
*/
angular.module('ui.directives', [])
.directive('uiDate', function () {
return {
require: '?ngModel',
//scope: {},
link: function ($scope, element, attrs, ngModel) {
// Date Handling Functions
var dateHandler = $.extend({ model: {}, view: {} }, $scope.$eval(attrs.uiDate));
// This will attempt to use preferredParser to parse a date.
function defaultDateParse(date, preferredParser) {
if (!preferredParser)
return new Date(date);
return preferredParser(date);
}
// This will attempt to use preferredFormatter to format a date, otherwise use 'mm/dd/yy'.
function defaultDateFormatter(date, preferredFormatter) {
if (!preferredFormatter)
preferredFormatter = "mm/dd/yy";
if (typeof preferredFormatter == 'string')
return $.datepicker.formatDate(preferredFormatter, date);
else
return preferredFormatter(date);
}
// Functions for Parsing & Formatting on the Model & View
function parseDateFromModel(date) {
return defaultDateParse(date, dateHandler.model.parse)
}
function parseDateFromView(date) {
return defaultDateParse(date, dateHandler.view.parse)
}
function formatDateForModel(date) {
return defaultDateFormatter(date, dateHandler.model.format)
}
function formatDateForView(date) {
return defaultDateFormatter(date, dateHandler.view.format)
}
var defaultDateViewFormat = (
typeof dateHandler.view.format == 'string'
? dateHandler.view.format
: 'mm/dd/yy'
)
// Initialize the jQuery-ui datePicker
var datePickerSettings = $.extend({ dateFormat: defaultDateViewFormat }, $scope.$eval(attrs.uiDatePicker))
var oldOnSelect = datePickerSettings.onSelect;
datePickerSettings.onSelect = function (dateVal) {
$scope.$apply(function () {
element.focus().val(dateVal);
updateModel();
})
if (oldOnSelect)
oldOnSelect.apply(this, arguments)
}
element.datepicker(datePickerSettings);
if (ngModel) {
// Specify how UI should be updated
ngModel.$render = function () {
element.val(ngModel.$viewValue || '');
};
// Listen for change events to enable binding
element.bind('blur keyup change', function () {
$scope.$apply(updateModel);
});
// Write data to the model
function updateModel() {
ngModel.$setViewValue(element.val());
}
// Convert the model into a string value
ngModel.$formatters.push(function (v) {
if (v != "" && v != null)
return formatDateForView(parseDateFromModel(v));
return null;
});
// Convert the string value into the model
ngModel.$parsers.push(function (v) {
if (v != "" && v != null)
return formatDateForModel(parseDateFromView(v))
return null;
});
}
}
};
})
Similar to praveepd (using their's as a base), but this will include deep model selection.
http://jsfiddle.net/c8PMa/
var myApp = angular.module('myApp', ['myApp.directives']);
function MainCtrl($scope) {
$scope.deepValue = {
fromDate: null,
toDate: null
}
}
angular.module('myApp.directives', [])
.directive('myDatepicker', function() {
return function(scope, element, attrs) {
element.datepicker({
changeYear : true,
changeMonth : true,
appendText : '(yyyy-mm-dd)',
dateFormat : 'yy-mm-dd',
onSelect: function(dateText) {
var mdlAttr = $(this).attr('ng-model').split(".");
if (mdlAttr.length > 1) {
var objAttr = mdlAttr[mdlAttr.length-1];
var s = scope[mdlAttr[0]];
for (var i=0; i < mdlAttr.length-2; i++) {
s = s[mdlAttr[i]];
}
s[objAttr] = dateText;
} else {
scope[mdlAttr[0]] = dateText;
}
scope.$apply();
}
});
}
});
http://jsfiddle.net/9BRNf/74/ here is the solution :)
code:
var myApp = angular.module('myApp', ['myApp.directives']);
function MainCtrl() {
}
angular.module('myApp.directives', [])
.directive('myDatepicker', function() {
return {
require: '?ngModel',
link: function (scope, element, attrs, ngModelCtrl) {
element.datepicker({
changeYear : true,
changeMonth : true,
appendText : '(yyyy-mm-dd)',
dateFormat : 'yy-mm-dd',
onSelect: function(date) {
ngModelCtrl.$setViewValue(date);
scope.$apply();
}
});
}
}
});
Old question, but this was the first hit for me in google search for this. Anyways, I used dual datepickers working together using jquery and angular directives, so I thought I'd share to help anyone else trying to do this.
Here's the plunker for it:
http://plnkr.co/edit/veEmtCM3ZnQAhGTn5EGy?p=preview
Basically it initializes the form using json. The datepickers have their own conditions like mindate's, etc. The first select box if true = disables sundays on the calendars, else enables them.
The viewmodel get's updates when 'done' is clicked. Here's a bit of the code for one of the datepickers:
Html:
<input id="StartDate" data-ng-model="viewModel.startdate" date-from />
Directive:
app.directive('dateFrom', function() {
return function (scope, element, attrs) {
var doDate = $('#EndDate');
element.datepicker({
dateFormat: 'dd-M-yy', showOtherMonths: true,
selectOtherMonths: true, minDate: '0',
beforeShowDay: function (date) {
var day = date.getDay();
console.log(scope.nosunday);
if (scope.nosunday === 'true') return [(day !== 0), '']; // disable sundays
else return [true, ''];
},
onSelect: function (selectedDate) {
var toDate = new Date(element.datepicker("getDate"));
toDate.setDate(toDate.getDate() + 1);
doDate.datepicker('option', 'minDate', toDate);
scope.viewModel.startdate = selectedDate;
scope.viewModel.enddate = doDate.val();
}
});
}
})
Feel free to optimize it further. Post a comment with a forked plunk if you do :)
I had just trimmed the code, have a look at this: http://jsfiddle.net/YU5mV/
HTML
<input id="date1" value="1/1/1980" ng-model="fromDate" my-datepicker />
<input id="date2" value="1/1/1980" ng-model="toDate" my-datepicker />
JavaScript
angular.module('myApp.directives', [])
.directive('myDatepicker', function() {
return function(scope, element, attrs) {
element.datepicker({
changeYear : true,
changeMonth : true,
appendText : '(yyyy-mm-dd)',
dateFormat : 'yy-mm-dd',
onSelect: function(dateText) {
var mdlAttr = $(this).attr('ng-model');
scope[mdlAttr] = dateText;
scope.$apply();
}
});
}
});