如何为ui-bootstrap日期选择器创建angularJs包装器指令? [英] How to create an angularJs wrapper directive for a ui-bootstrap datepicker?

查看:104
本文介绍了如何为ui-bootstrap日期选择器创建angularJs包装器指令?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用 ui.bootstrap.datepicker 指令显示一些日期字段.但是,大多数时候我需要相同的设置:我希望它带有弹出窗口和弹出按钮,并且我还希望文本使用德语名称.确实会为按钮,文本和格式重复创建相同的代码,因此我编写了自己的指令以防止自己重复.

I am using the ui.bootstrap.datepicker directive to display some date field. However most of the time I need the same setup: I want it to come along with a popup and a popup button and also I want German names for the texts. That does create the same code for the button and the texts and the formatting over and over again, so I wrote my own directive to prevent myself from repeating myself.

这是我指令下的plunkr .但是我似乎做错了.如果您使用不使用我的指令的日期1"日期选择器通过日期选择器选择日期,则一切正常. 我希望日期2也是一样,但是它不是根据我在输入字段中提供的模板显示日期(或我期望的任何其他值),而是显示日期对象的.toString()表示形式(例如Fri Apr 03 2015 00:00:00 GMT+0200 (CEST) ).

Here is a plunkr with my directive. However I seem to be doing it wrong. If you choose a date with the date picker using the "Date 1" datepicker that does not use my directive everything works fine. I'd expect the same for Date 2, but instead of displaying the date according to the template I supplied in the input field (or any other value I expected) it displays the .toString() representation of the date object (e.g. Fri Apr 03 2015 00:00:00 GMT+0200 (CEST)).

这是我的指令:

angular.module('ui.bootstrap.demo').directive('myDatepicker', function($compile) {
  var controllerName = 'dateEditCtrl';
  return {
      restrict: 'A',
      require: '?ngModel',
      scope: true,
      link: function(scope, element) {
          var wrapper = angular.element(
              '<div class="input-group">' +
                '<span class="input-group-btn">' +
                  '<button type="button" class="btn btn-default" ng-click="' + controllerName + '.openPopup($event)"><i class="glyphicon glyphicon-calendar"></i></button>' +
                '</span>' +
              '</div>');

          function setAttributeIfNotExists(name, value) {
              var oldValue = element.attr(name);
              if (!angular.isDefined(oldValue) || oldValue === false) {
                  element.attr(name, value);
              }
          }
          setAttributeIfNotExists('type', 'text');
          setAttributeIfNotExists('is-open', controllerName + '.popupOpen');
          setAttributeIfNotExists('datepicker-popup', 'dd.MM.yyyy');
          setAttributeIfNotExists('close-text', 'Schließen');
          setAttributeIfNotExists('clear-text', 'Löschen');
          setAttributeIfNotExists('current-text', 'Heute');
          element.addClass('form-control');
          element.removeAttr('my-datepicker');

          element.after(wrapper);
          wrapper.prepend(element);
          $compile(wrapper)(scope);

          scope.$on('$destroy', function () {
              wrapper.after(element);
              wrapper.remove();
          });
      },
      controller: function() {
          this.popupOpen = false;
          this.openPopup = function($event) {
              $event.preventDefault();
              $event.stopPropagation();
              this.popupOpen = true;
          };
      },
      controllerAs: controllerName
  };
});

这就是我的使用方式:

<input my-datepicker="" type="text" ng-model="container.two" id="myDP" />

(概念的灵感来自此答案)

我正在使用角度1.3(插塞在1.2上,因为我只是从 angular分叉了-ui-bootstrap datepicker文档).我希望这不会有任何改变.

I am using angular 1.3 (the plunker is on 1.2 because I just forked the plunker from the angular-ui-bootstrap datepicker documentation). I hope this does not make any difference.

为什么输入中的文本输出错误以及如何正确完成?

与此同时,我取得了一些进展.在阅读了有关编译和链接的更多信息之后,在此插件中,我使用了编译功能,而不是链接函数来执行我的DOM操作.我仍然对文档的摘录有些困惑:

In the meantime I made a little progress. After reading more about the details about compile and link, in this plunkr I use the compile function rather than the link function to do my DOM manipulation. I am still a little confused by this excerpt from the docs:

注意:如果已克隆模板,则模板实例和链接实例可能是不同的对象.因此,除了将DOM转换应用于编译函数中所有克隆的DOM节点之外,执行其他任何操作都是不安全的.具体来说,DOM侦听器注册应该在链接功能中完成,而不是在编译功能中完成.

Note: The template instance and the link instance may be different objects if the template has been cloned. For this reason it is not safe to do anything other than DOM transformations that apply to all cloned DOM nodes within the compile function. Specifically, DOM listener registration should be done in a linking function rather than in a compile function.

我特别想知道适用于所有克隆的DOM节点"的含义.我本来以为这意味着适用于DOM模板的所有克隆",但事实并非如此.

Especially I wonder what is meant with "that apply to all cloned DOM nodes". I originally thought this means "that apply to all clones of the DOM template" but that does not seem to be the case.

无论如何:我的新编译版本可在Chrome中正常运行.在Firefox中,我需要先使用日期选择器选择一个日期,然后一切正常(如果我将undefined更改为null( plunkr ).所以这也不是最新的事情.另外,我使用ng-model2而不是在编译过程中重命名的ng-model.如果我不这样做,一切仍然会破裂.还是不知道为什么.

Anyhow: My new compile version works fine in chromium. In Firefox I need to first select a date using a date picker and after that everything works fine (the problem with Firefox solved itself if I change undefined to null (plunkr) in the date parser of the date picker). So this isn't the latest thing either. And additionally I use ng-model2 instead of ng-model which I rename during compile. If I do not do this everything is still broken. Still no idea why.

推荐答案

当您将以下两行添加到指令定义中时,您的指令将起作用:

Your directive will work when you add these 2 lines to your directive definition:

return {
    priority: 1,
    terminal: true,
    ...
 }

这与指令的执行顺序有关.

This has to do with the order in which directives are executed.

所以在您的代码中

<input my-datepicker="" type="text" ng-model="container.two" id="myDP" />

有两个指令:ngModelmyDatepicker.您可以优先使自己的指令在ngModel之前执行.

There are two directives: ngModel and myDatepicker. With priority you can make your own directive execute before ngModel does.

这篇关于如何为ui-bootstrap日期选择器创建angularJs包装器指令?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆