6

First, I should mention I am just working on transitioning to clientside programming. I am very new to js. My previous experience is primarily in C and some assembly. I also did a bit of very simple php years ago when it was still 4.0. So in short, new to javascript but putting my head around it a bit.

I have done quite a bit of searching and lurking but have not been able to rectify my issues.

I am figuring out some of the basics of AngularJS and it is quite nice, but I am having difficulty wrapping my head around how directives work and how to access data from custom controls.

Long story short I am trying to make a custom control for bootstrap work with angularjs so I can use it in forms properly.

Here is the control: http://tarruda.github.com/bootstrap-datetimepicker/

I have some other controls that I want to make work but I figure if I can get this one going I can probably get the others easily enough.

Here is a link to a basic framework what I have at this point: http://jsfiddle.net/uwC9k/6/

First off, I am trying to wrap my head around how to initialize the control once I have the template working (Which, I pretty much do at this point I think)

link: function(scope, element, attr) {
            attr.$observe('dpid', function(value) {
                if(value) {
              $('#' + scope.dpid).datetimepicker({
                  language: 'en',
                  pick12HourFormat: true
            });
}

When I put that in the link directive, it does nothing. I don't even see any errors. scope.dpid is indeed showing the ID of the control so I thought it would work. But alas, my febble understanding of javascript tells me that I am outside of the scope or some such nonsense where I cannot access the element.

Once I get that going, I am not exactly sure how to make this data accessible in forms either.

Any help is greatly appreciated.

Update Got the basic bit working, now I need to know how to get the data from the new control into my controller. Here is a link to the new jsfiddle updated. http://jsfiddle.net/tmZDY/1/

Update 2 I think I have an idea on how to make this data accessible but my lacking knowledge of javascript has left me dry again.

when I create the object I do it thusly.

var elDatepicker = element.datetimepicker({
language : 'en',
pick12HourFormat : true,
});

However, when I try to use this object it does not seem to be getting the correct one, or I am just missing some basic knowledge. Either way this is sure making me feel foolish.

console.log(elDatepicker.getDate());

This fails, getDate is indeed a method, at least it looks like it is in the code of the plugin.

Mark Rajcok
  • 362,217
  • 114
  • 495
  • 492
Patrick B
  • 75
  • 2
  • 6
  • This isn't a forum it's a Q&A site, you should ask each question separately. Similarly, if you have an answer to your own question, post it as an answer, don't update the original question. – Soviut Oct 27 '13 at 09:32

3 Answers3

3

Instead of an isolate scope, you can find() the first div of your template and then apply datetimepicker(). So you don't need an id in your HTML:

<datepicker model="mydate"></datepicker>
mydate = {{mydate}}

I also suggest replace: true:

.directive('datepicker', function ($parse) {
    return {
        restrict: 'E',
        replace: true,
        template: '<div class=\"well\"><div class=\"input-append\">'
         + '<input data-format=\"MM/dd/yyyy HH:mm:ss PP\" type=\"text\"></input>'
         + '<span class=\"add-on\"><i data-time-icon=\"icon-time\" data-date-icon=\"icon-calendar\"></i></span>'
         + '</div></div>',
        link: function (scope, element, attr) {
            var picker = element.find('div').datetimepicker({
                language: 'en',
                pick12HourFormat: true
            });
            var model = $parse(attrs.model);
            picker.on('changeDate', function(e) {
               console.log(e.date.toString());
               console.log(e.localDate.toString());
               model.assign(scope, e.date.toString());
               scope.$apply();
           });
        }
    };
})

Fiddle

$parse is a bit tricky. What I show is the main use case for it: we parse an attribute and get back a function which has an assign() method on it that allows us to change the scope property.

Mark Rajcok
  • 362,217
  • 114
  • 495
  • 492
  • Great, this solved the first bit. Now I just need to figure out how to update data in my controller with what is in the field. Updated a jsfiddle with what I am trying. Not going so well! – Patrick B Mar 21 '13 at 04:01
  • @Patrick, I haven't used that plugin. You'll need to configure it to call a function when the value changes... maybe an onSelect option or something. Then update a scope property with the new value inside the callback function. You may also need to call scope.$apply(), if your are showing the data via Angular. This answer about datepicker might help: http://stackoverflow.com/a/11880559/215945 – Mark Rajcok Mar 21 '13 at 14:33
  • I see, thank you so much for your helpthusfar. I am really having difficulty accessing the datetimepicker. I (think) I can see the function I need to use to get the value/date but I can't seem to access the object. when I use element.getDate() or any of the other prototypes it says that the method does not exist. Not exactly sure how to access it. Updated the first post to show some more code. – Patrick B Mar 21 '13 at 19:54
  • @Patrick, I looked at the docs and what we want is the `changeDate` event. See my updated answer and fiddle. – Mark Rajcok Mar 21 '13 at 20:19
  • Wonderful, I figured out how to make it link/update the model and it's exactly what I need! Thanks so much for the help, I learned a lot. `scope.$apply( function(){ ctrl.$setViewValue(e.localDate.toString()); });` – Patrick B Mar 21 '13 at 22:20
  • @Patrick, instead of using ng-model (and $setViewValue and requiring the ngModelController), you can use an attribute to specify which $scope property you want the datetime picker to update. $parse is required to get this to work. I edited my answer and fiddle to show you how that all works. – Mark Rajcok Mar 22 '13 at 03:35
0

One of the way to do may be this, as shown in this fiddle. http://jsfiddle.net/uwC9k/10/

As the datepicker element has to be replaced with the template string, this will be a good use case to use the compile function. So inside the compile function im replacing the datepicker element with the template string.

Once the compling is done, we will go to the link function, which is nothing but the function returned from inside the compile function. What the linking function will do is to initialize this <div class=\"input-append\"> element with date picker functionality using

element.datetimepicker({
                      language: 'en',
                      pick12HourFormat: true
                });

Since you are including the jquery, the element attribute in the linking function is a jquery warpped element. So you can straight away call the datetimepicker method.

Rajkamal Subramanian
  • 6,884
  • 4
  • 52
  • 69
  • "As the datepicker element has to be replaced with the template string, this will be a good use case to use the compile function." -- this is what `replace: true, template: ...,` does for you automatically. I.e., no need for a compile function. – Mark Rajcok Mar 21 '13 at 14:21
0

You can add a class like datetimepicker to the div which has to be converted to the datetimepicker, then use that class to look up for the element.

.directive('datepicker', function() {
    return {
        restrict: 'E',
        template: '<div class=\"well\"><div id={{dpid}} class=\"input-append datetimepicker\"><input data-format=\"MM/dd/yyyy HH:mm:ss PP\" type=\"text\"></input>    <span class=\"add-on\"><i data-time-icon=\"icon-time\" data-date-icon=\"icon-calendar\">      </i>    </span>  </div></div>',
        scope: { dpid: '@'},
        link: function(scope, element, attr) {
            attr.$observe('dpid', function(value) {
                if(value) {
              $(element).find('.datetimepicker').datetimepicker({
                  language: 'en',
                  pick12HourFormat: true
            });
                }
            });
        }
    };
})

Demo: Fiddle

Arun P Johny
  • 384,651
  • 66
  • 527
  • 531