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

查看:21
本文介绍了如何为 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.但是我似乎做错了.如果您使用不使用我的指令的Date 1"日期选择器选择带有日期选择器的日期,则一切正常.我希望 Date 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
  };
});

这就是我使用它的方式:

And that's how I use it:

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

(概念的灵感来自这个答案)

我使用的是 angular 1.3(plunker 在 1.2 上,因为我刚刚从 angular 分叉了 plunker-ui-bootstrap 日期选择器文档).我希望这没有任何区别.

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.

为什么我输入中的文本输出是错误的,它是如何正确输出的?

与此同时,我取得了一些进展.在阅读了有关编译和链接的详细信息后,在 this plunkr 中,我使用了编译功能而不是链接函数来做我的 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:

注意:如果模板已经被克隆,模板实例和链接实例可能是不同的对象.出于这个原因,除了适用于 compile 函数中所有克隆的 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,Firefox 的问题就会自行解决(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.

推荐答案

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

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天全站免登陆