AngularJS的ng模型绑定澄清?

时间:2014-02-02 08:21:36

标签: javascript angularjs

  

ng-model绑定输入,选择,textarea(或自定义表单控件)   使用创建的NgModelController创建范围内的属性   并且通过该指令公开。

但是看一下这个简单的代码here会引发两个问题:

<div ng-app="myApp" ng-controller="MainCtrl">
     Name: <input type="text" ng-model="ctrl.name.aaa.lalala"/><input type='button' value='done'/>
    <br/><br/><br/>
    <div>
         Welcome, {{ctrl.name.aaa.lalala}}
    </div>
</div>
<script>
    function MainCtrl($scope) {}
</script>

视觉:

enter image description here

问题

1)每次更改输入值时 - 它会自动更改范围属性。我相信它是如何运作的。但是,如果我只想 按下按钮后才接受数据呢?一个解决方案是在范围内添加一个标记:"isPressed"但我认为它非常错误。如何更改我的代码呢?

2)ng-model="ctrl.name.aaa.lalala"如何运作? 我希望得到一个例外。的为什么

因为我知道我应该这样做:

$scope.name={};
$scope.name.aaa={};

然后它会起作用。

但它的工作原理就像没有预定义对象。我错过了什么?

2 个答案:

答案 0 :(得分:2)

1)我会创建一个这样的自定义指令来保存未提交的值,并且只在单击按钮时提交它:

 app.directive("commitableValue",function(){
     return {
      require: '^ngModel',
      restrict: 'A',
      link: function(scope, element, attrs, ngModel) {
        var committed; 
        var committedValue;

        ngModel.$parsers.push(function(value){
          return committed ? value : committedValue; //return uncommitted value to the pipeline if the button is not clicked
        });

        scope.$watch(function(){ //Whenever ngModel.$modelValue changes, reset the values. This also deals with the case when another code updates the same property.
          return ngModel.$modelValue;
        },function (value){
          committedValue = ngModel.$modelValue; 
          committed = false;
        });

        scope.$on("commitValue",function(event){ 
          committed = true; //when receiving an event to commit the value, update the underlying model's property
          ngModel.$setViewValue(ngModel.$viewValue);
        });

      }
    };
  });

然后在单击按钮后需要保存的字段上应用此指令:

<input type="text" commitable-value ng-model="ctrl.name.aaa.lalala"/>

单击该按钮时,我们广播一个事件以通知所有指令提交其值:

<input type='button' value='done' ng-click="commitValue()"/>

JS:

$scope.commitValue = function(){
     $scope.$broadcast("commitValue");
}

DEMO

2)ng-model将自动为您创建属性在第一次之后如果未定义属性,则更改值。从第二次开始,属性已经存在,angular将只更新值。

答案 1 :(得分:2)

我真的很喜欢Khanh TO的答案,但是这里有一个不同的解决方案,当你有一个你可能想要或不想用来更新模型的许多属性的表单时效果很好。

假设您有一个表单来更新此模型代表某个人的个人详细信息:

{
    firstname: 'wackford',
    lastname: 'squeers',
    phone: '1234 567890'
}

,您的模型包含以下内容:

$scope.users = [ {}, {}, {} ];

当您开始编辑用户时,您会将用户复制到另一个范围属性,例如

$scope.userUnderEdit =  angular.copy( $scope.user[0] );

如果您在UI上按提交,则会将已编辑的用户复制回用户集合:

$scope.commitUserChanges = function(){
    $scope.users[0] = angular.copy( $scope.usersUnderEdit );
    // persist data etc.
}

如果用户取消编辑,则只需清除userUnderEdit:

$scope.cancelUserChanges = function(){
    $scope.usersUnderEdit = null;
}

演示: Fiddle