javascript - 无法将 ng 自定义指令的日期选择器结果绑定(bind)到 html 输入字段中的 ng-model

标签 javascript angularjs dom angularjs-directive

我是 js 和 Angular.js 的初学者。我需要一些帮助,将 Angular 自定义指令中的日期选择器返回的结果绑定(bind)到 HTML 输入字段中的 ng-model。这里是 -

我的 HTML 表单使用 ng-controller 从后端数据库检索数据以填充元素,其中包括日期字段。可以使用附加的日期选择器更新此日期字段。鉴于 Jquery 日期选择器无法在 FireFox 和 Safari 浏览器中使用 angular.js,我编写了一个自定义 ng 指令来实现日期选择器。但是,我在获取从自定义指令返回的结果以替换 HTML 中的原始日期字段时遇到问题。

在我的 HTML 中,日期输入字段有 ng-model="myCtrl.deadline" ,而我的自定义指令有 "scope.deadline = date;" - 没有"myCtrl"字首。如果我设置ng-model="deadline"那么日期字段将不会由从后端提取的初始数据填充。如果我设置ng-model={{deadline}}当我从日期选择器中选择新日期时,我在浏览器中收到 angular.min.js 错误。

自定义指令中的日期选择器工作正常,我可以在 HTML 日期字段中选择一个新日期,但新日期未绑定(bind)到 HTML 字段。因此,没有办法区分。新值与以前的值来检测更改并触发新日期值到后端的更新。

这是我的代码的样子:

代码

<html ng-app="myApp" ng-controller="MyCtrl as myCtrl">
<head>
      <script src="js/angular.min.js"></script>
      <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.3/angular-messages.js"></script>

    <title>Edit your data</title>
</head>
<body>
<div class="container">
...
       <div  class="row">
          <div class="col-sm-4 col-md-4"><strong>Deadline:</strong></div>
          <div class="col-sm-8 col-md-8">
          <input type="text" 
            class="form-control" 
            id="theDate"
            ng-model="myCtrl.deadline" 
            ng-blur="myCtrl.update('deadline')"
            ng-change="myCtrl.update('deadline')"
            required jq-date-picker><span class="glyphicon glyphicon-calendar" aria-hidden="true"></span></div>
       </div>
<div>
...
</body>
<script type="text/javascript">
    var app = angular.module('myApp', ['ngMessages']);
    app.controller(
            'MyCtrl',
            ['$http','$location','$timeout', function($http, $location, $timeout) {
                        var self = this;
                        self.Id="";
                        ...                     
                        self.deadline = "";
                        self.prevDeadline = "";

            // function begin
            //handles updates on the page
            self.update = function(varname){
                      var changed = false;
                     // the 2 statements show self.deadline not get updated
                     // with the new date value from the custom directive
                     // can't diff. with prevDeadline to detect a change  
                      console.log("prev.DeadLine: " + self.prevDeadline);
                      console.log("new.deadLine: " + self.deadline);
                     ...
            }

            //retrieve data initially
            self.getData = function(Id){
                            $http.get('/rest/v3/getData/',{params:{betId: betId}}).then(
                                    function(response){
                                            var data = response.data;
                                            ....
                                            self.deadline = data.deadline;
                                            self.prevDeadline = self.deadline;
                                            ...
                            );
                        }

                    } ]);

    app.directive('jqDatePicker', function (){
          return {
              restrict: 'A',
              require: 'ngModel',
              link: function (scope, element, attrs, ngModelCtrl) {
                  element.datepicker({
                      dateFormat: 'D, d MM yy',
                      onSelect: function (date) {
                          scope.deadline = date;
                          scope.$apply();
                      }
                  });
              }
          };
      });

</script>
</html>

很抱歉这篇文章很长。我是一个新手,发现使用 Angular UI Bootstrap 方法来解决这个问题对于我目前的理解来说有点太超前了。感谢您的帮助。

后续问题:如果我使用像此演示代码中那样的 Angular 日期选择器方法 https://angular-ui.github.io/ui-date/ ,指令代码如下所示

      angular.module('MyApp', ['ui.date'])
      .controller('MyCtrl', function($scope) {
          $scope.aDate = '2015-10-31';
          $scope.dateOptions = {
             dateFormat: 'dd.mm.yy',
          }
      })

我现有的 Controller 代码如下所示

    var app = angular.module('myApp', ['ngMessages']);
    app.controller(
        'MyCtrl',
        ['$http','$location','$timeout', function($http, $location, $timeout) {
            var self = this;
            self.Id="";
            ... 
            self.deadline = "";
            self.prevDeadline = "";
            ... 
    } ]);

如何将两个代码片段合并在一起?会是这样吗?

    var app = angular.module('myApp', ['ui.date', 'ngMessages']);
    app.controller(
        'MyCtrl',
        ['$http','$location','$timeout', '$scope', function($http, $location, $timeout, $scope) {
        var self = this;
        self.Id="";
        ... 
        self.deadline = "";
        self.prevDeadline = "";
        ...
        $scope.aDate = '2015-10-31';
        $scope.dateOptions = {
        dateFormat: 'dd.mm.yy', 
        ... 
    } ]); 

我发现 Angular.org 文档和教程对于初学者来说不太容易理解。到目前为止,我一直依靠在网络上查找代码示例来编写我需要的代码。我想正确学习 Angular 自定义指令,这样我就可以针对不同的要求进行编码,而不是在找不到要复制和粘贴的代码示例时陷入困境。非常感谢您的帮助。

最佳答案

您只需要:

ngModelCtrl.$setViewValue(date);

在:

app.directive('jqDatePicker', function() {
    return {
      restrict: 'A',
      require: 'ngModel',
      link: function(scope, element, attrs, ngModelCtrl) {
        $(element).datepicker({
          dateFormat: 'D, d MM yy',
          onSelect: function(date) {
            ngModelCtrl.$setViewValue(date); // <--
          }
        });
      }
    };
  });

ngModel.NgModelController:

NgModelController provides API for the ngModel directive. The controller contains services for data-binding, validation, CSS updates, and value formatting and parsing. It purposefully does not contain any logic which deals with DOM rendering or listening to DOM events. Such DOM related logic should be provided by other directives which make use of NgModelController for data-binding to control elements.

$setViewValue(value, trigger):

Update the view value.

This method should be called when a control wants to change the view value; typically, this is done from within a DOM event handler. For example, the input directive calls it when the value of the input changes and select calls it when an option is selected.

类似这样的事情:

(function() {
  var app = angular.module('myApp', ['ngMessages']);
  app.controller('MyCtrl', ['$http', '$location', '$timeout', function($http, $location, $timeout) {
    var self = this;
    self.Id = "";
    self.deadline = "";
    self.prevDeadline = "";

    //retrieve data initially
    self.getData = function(Id) {
      $http.get('/rest/v3/getData/', {
        params: {
          betId: betId
        }
      }).then(function(response) {
        var data = response.data;

        self.deadline = data.deadline;
        self.prevDeadline = self.deadline;
      }, function(response) {
        console.log(response);
      });
    };
  }]);

  app.directive('jqDatePicker', function() {
    return {
      restrict: 'A',
      require: 'ngModel',
      link: function(scope, element, attrs, ngModelCtrl) {
        $(element).datepicker({
          dateFormat: 'D, d MM yy',
          onSelect: function(date) {
            ngModelCtrl.$setViewValue(date);
          }
        });
      }
    };
  });
})();
<link rel="stylesheet" type="text/css" href="https://code.jquery.com/ui/1.12.1/themes/base/jquery-ui.css">
<script type="text/javascript" src="//cdnjs.cloudflare.com/ajax/libs/angular.js/1.4.8/angular.js"></script>
<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.3/angular-messages.js"></script>
<script type="text/javascript" src="https://code.jquery.com/jquery-1.12.4.js"></script>
<script type="text/javascript" src="https://code.jquery.com/ui/1.12.1/jquery-ui.js"></script>

<div data-ng-app="myApp">
  <div data-ng-controller="MyCtrl as myCtrl">

    <div class="container">
      <div class="row">
        <div class="col-sm-4 col-md-4"><strong>Deadline:</strong></div>
        <div class="col-sm-8 col-md-8">
          <input type="text" class="form-control" id="theDate" ng-model="myCtrl.deadline" required jq-date-picker><span class="glyphicon glyphicon-calendar" aria-hidden="true"></span></div>
      </div>
      <div>
        Selected Date: {{myCtrl.deadline}}
      </div>
    </div>
  </div>
</div>

<小时/>

使用https://angular-ui.github.io/ui-date/assets/date.js :

  1. 您需要添加此 JavaScript 外部文件: ( https://angular-ui.github.io/ui-date/assets/date.js ) 在您的页面中。
  2. 在文本框日期字段中添加 ui-date="dateOptions"
  3. 在模块中注入(inject) 'ui.date' 依赖项。
  4. 在 Controller 中添加 '$scope'

类似这样的事情:

(function() {
  var app = angular.module('myApp', ['ngMessages', 'ui.date']);
  app.controller('MyCtrl', ['$scope', '$http', '$location', '$timeout', function($scope, $http, $location, $timeout) {
    var self = this;
    self.Id = "";
    self.deadline = "06.10.2015";
    self.prevDeadline = "";


    $scope.dateOptions = {
      dateFormat: 'dd.mm.yy',
    };

    //retrieve data initially
    self.getData = function(Id) {
      $http.get('/rest/v3/getData/', {
        params: {
          betId: betId
        }
      }).then(function(response) {
        var data = response.data;

        self.deadline = data.deadline;
        self.prevDeadline = self.deadline;
      }, function(response) {
        console.log(response);
      });
    };
  }]);
})();
<link rel="stylesheet" type="text/css" href="https://code.jquery.com/ui/1.12.1/themes/base/jquery-ui.css">
<script type="text/javascript" src="//cdnjs.cloudflare.com/ajax/libs/angular.js/1.4.8/angular.js"></script>
<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.3/angular-messages.js"></script>
<script type="text/javascript" src="https://code.jquery.com/jquery-1.12.4.js"></script>
<script type="text/javascript" src="https://code.jquery.com/ui/1.12.1/jquery-ui.js"></script>
<script src="https://angular-ui.github.io/ui-date/assets/date.js"></script>

<div data-ng-app="myApp">
  <div data-ng-controller="MyCtrl as myCtrl">

    <div class="container">
      <div class="row">
        <div class="col-sm-4 col-md-4"><strong>Deadline:</strong></div>
        <div class="col-sm-8 col-md-8">
          <input type="text" class="form-control" id="theDate" ng-model="myCtrl.deadline" required ui-date="dateOptions"><span class="glyphicon glyphicon-calendar" aria-hidden="true"></span></div>
      </div>
      <div>
        Selected Date: {{myCtrl.deadline}}
      </div>
    </div>
  </div>
</div>

希望这有帮助。

关于javascript - 无法将 ng 自定义指令的日期选择器结果绑定(bind)到 html 输入字段中的 ng-model,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44148365/

相关文章:

javascript - AnalyserNode 在什么时候执行 FFT?

javascript - 动态指定要在 Angular 指令中使用的 Controller

javascript - 如何从使用 addEventListener 添加的事件的元素中删除类?

Javascript - 获取 child 的文本值

javascript - 在 Javascript 中交换整个数组

javascript - 无法在 PrestaShop 中引用 HTTPS SVG

javascript - 带功能的 ionic 自动完成取消标签

javascript - 如何在javascript中获取准确的源域地址

javascript - Leaflet - onEachFeature 鼠标悬停更新表格的 innerHTML

javascript - 如何实现 iframe 元素选择器? (如 Chrome )