如何为 ui-bootstrap 日期选择器创建 angularJs 包装器指令?

2023-12-26

我正在使用ui.bootstrap.datepicker https://angular-ui.github.io/bootstrap/显示某些日期字段的指令。然而,大多数时候我需要相同的设置:我希望它带有一个弹出窗口和一个弹出按钮,而且我还想要文本的德语名称。这确实会一遍又一遍地为按钮、文本和格式创建相同的代码,因此我编写了自己的指令以防止自己重复。

这是一个笨蛋 http://plnkr.co/edit/eXxBnZ7ArHvhA6fQAxDL?p=preview按照我的指示。然而我似乎做错了。如果您使用“日期 1”日期选择器的日期选择器选择一个日期,而该日期选择器不使用我的指令,则一切正常。 我希望日期 2 也是如此,但它不是根据我在输入字段中提供的模板(或我期望的任何其他值)显示日期,而是显示.toString()日期对象的表示(例如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" />

(概念的灵感来自这个答案 https://stackoverflow.com/a/27605580/327301)

我正在使用 Angular 1.3(plunker 位于 1.2 上,因为我刚刚从角度 ui 引导程序 http://angular-ui.github.io/bootstrap/日期选择器文档)。我希望这不会产生任何影响。

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

Update

与此同时,我取得了一些进步。在阅读了有关编译和链接的更多详细信息后,这个笨蛋 http://plnkr.co/edit/gtQzzH6fnv5Zjxc9vf9M我使用编译函数而不是链接函数来进行 DOM 操作。我对文档中的这段摘录仍然有点困惑:

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

我特别想知道“适用于所有克隆的 DOM 节点”是什么意思。我最初认为这意味着“适用于 DOM 模板的所有克隆”,但事实似乎并非如此。

无论如何:我的新编译版本在 Chromium 中运行良好。在 Firefox 中,我需要首先使用日期选择器选择一个日期,之后一切正常(如果我将 undefined 更改为 null,Firefox 的问题就会自行解决(plunkr http://plnkr.co/edit/Oc069LSf42BE5N54IpBQ)在日期选择器的日期解析器中)。所以这也不是最新的事情。另外我用ng-model2代替ng-model我在编译期间重命名。如果我不这样做,一切仍然会被破坏。还是不知道为什么。


老实说,我不太清楚为什么会造成这种情况,以及是什么导致您的日期在输入中显示之前被“toString-ed”。

但是,我确实找到了重组指令的地方,并删除了许多不必要的代码,例如$compile服务、属性更改、范围继承、require在指令等中。我使用了独立的作用域,因为我不认为每个指令的使用都应该知道父作用域,因为这可能会导致未来出现恶性错误。这是我更改的指令:

angular.module('ui.bootstrap.demo').directive('myDatepicker', function() {
  return {
      restrict: 'A',
      scope: {
          model: "=",
          format: "@",
          options: "=datepickerOptions",
          myid: "@"
      },
      templateUrl: 'datepicker-template.html',
      link: function(scope, element) {
          scope.popupOpen = false;
          scope.openPopup = function($event) {
              $event.preventDefault();
              $event.stopPropagation();
              scope.popupOpen = true;
          };

          scope.open = function($event) {
            $event.preventDefault();
            $event.stopPropagation();
            scope.opened = true;
          };

      }
  };
});

你的 HTML 用法就变成了:

<div my-datepicker model="container.two" 
                   datepicker-options="dateOptions" 
                   format="{{format}}"  
                   myid="myDP">
</div>

Edit:添加了id作为指令的参数。普朗克已更新。

Plunker http://plnkr.co/edit/xE8XMLozp7ufdUHfNA76?p=preview

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何为 ui-bootstrap 日期选择器创建 angularJs 包装器指令? 的相关文章

随机推荐