首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >如何为ui-bootstrap datepicker创建angularJs包装器指令?

如何为ui-bootstrap datepicker创建angularJs包装器指令?
EN

Stack Overflow用户
提问于 2015-04-10 21:05:00
回答 8查看 13.5K关注 0票数 50

我使用ui.bootstrap.datepicker指令来显示一些日期字段。然而,大多数时候,我需要相同的设置:我希望它来与一个弹出式和弹出式按钮,我还想为文本的德国名字。这确实为按钮、文本和格式一遍又一遍地创建了相同的代码,因此我编写了自己的指令,以防止自己重复自己。

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

以下是我的指令:

代码语言:javascript
复制
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
  };
});

这就是我使用它的方式:

代码语言:javascript
复制
<input my-datepicker="" type="text" ng-model="container.two" id="myDP" />

(概念的灵感来自this answer)

我使用的是angular 1.3 (柱塞在1.2上,因为我刚从angular-ui-bootstrap datepicker文档中派生了柱塞)。我希望这不会有什么不同。

为什么我的输入中的文本输出是错误的,以及如何正确地进行输出?

更新

在此期间,我取得了一些进展。在阅读了更多关于编译和链接的详细信息之后,在this plunkr中,我使用编译函数而不是链接函数来执行DOM操作。我仍然对文档中的这段摘录感到有点困惑:

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

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

无论如何:我的新编译版本在chromium中工作得很好。在火狐中,我首先需要使用日期选择器选择一个日期,然后一切正常(如果我在日期选择器的日期解析器中将undefined更改为null (plunkr),Firefox的问题就解决了)。所以这也不是最新的东西。此外,我使用ng-model2而不是ng-model,它是我在编译时重命名的。如果我不这样做,一切仍然是坏的。还是不知道为什么。

EN

回答 8

Stack Overflow用户

回答已采纳

发布于 2015-04-16 16:25:23

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

代码语言:javascript
复制
return {
    priority: 1,
    terminal: true,
    ...
 }

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

所以在你的代码中

代码语言:javascript
复制
<input my-datepicker="" type="text" ng-model="container.two" id="myDP" />

有两个指令:ngModelmyDatepicker。有了优先级,你可以让你自己的指令在ngModel之前执行。

票数 9
EN

Stack Overflow用户

发布于 2015-04-12 22:07:01

老实说,我不太确定为什么会这样,以及是什么导致你的日期在输入中显示之前被"toString-ed“。

但是,我确实找到了重构指令的地方,并删除了许多不必要的代码,如$compile服务、属性更改、范围继承、指令中的require等。我使用了隔离作用域,因为我不认为每个指令的用法都应该知道父作用域,因为这可能会导致恶意的bug。这是我修改后的指令:

代码语言:javascript
复制
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使用变成了:

代码语言:javascript
复制
<div my-datepicker model="container.two" 
                   datepicker-options="dateOptions" 
                   format="{{format}}"  
                   myid="myDP">
</div>

编辑:将id作为参数添加到指令中。Plunker已更新。

Plunker

票数 17
EN

Stack Overflow用户

发布于 2015-04-15 20:12:18

我认为@omri-aharon的答案是最好的,但我想指出一些这里没有提到的改进:

Updated Plunkr

您可以使用config统一设置您的选项,如格式和文本选项,如下所示:

代码语言:javascript
复制
angular.module('ui.bootstrap.demo', ['ui.bootstrap'])
.config(function (datepickerConfig, datepickerPopupConfig) {
  datepickerConfig.formatYear='yy';
  datepickerConfig.startingDay = 1;
  datepickerConfig.showWeeks = false;
  datepickerPopupConfig.datepickerPopup = "shortDate";
  datepickerPopupConfig.currentText = "Heute";
  datepickerPopupConfig.clearText = "Löschen";
  datepickerPopupConfig.closeText = "Schließen";
});

我发现这更清晰,更容易更新。这也允许你极大地简化指令、模板和标记。

自定义指令

代码语言:javascript
复制
angular.module('ui.bootstrap.demo').directive('myDatepicker', function() {
  return {
      restrict: 'E',
      scope: {
          model: "=",
          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;
          };

      }
  };
});

模板

代码语言:javascript
复制
<div class="row">
    <div class="col-md-6">
        <p class="input-group">
          <input type="text" class="form-control" id="{{myid}}" datepicker-popup ng-model="model" is-open="opened" ng-required="true"  />
          <span class="input-group-btn">
            <button type="button" class="btn btn-default" ng-click="open($event)"><i class="glyphicon glyphicon-calendar"></i></button>
          </span>
        </p>
    </div>
</div> 

如何使用它

代码语言:javascript
复制
<my-datepicker model="some.model" myid="someid"></my-datepicker>

此外,如果希望强制使用德语区域设置格式,可以添加angular- locale _de.js。这确保了像'shortDate'这样的日期常量使用的一致性,并强制使用德语的月份和日期名称。

票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/29562213

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档