加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 综合聚焦 > 服务器 > 安全 > 正文

angularjs – 当检查$pristine或$setDirty()时,为什么要在ng-inc

发布时间:2020-12-17 08:23:58 所属栏目:安全 来源:网络整理
导读:以下代码在单击“检查”按钮时抛出错误“TypeError:无法读取属性未定义的$ pristine”。 app.controller('MainCtrl',function($scope) { // other stuff}).controller('Ctrl2',function($scope) { $scope.product = {description:'pump'}; $scope.output =
以下代码在单击“检查”按钮时抛出错误“TypeError:无法读取属性未定义的$ pristine”。
app.controller('MainCtrl',function($scope) {
  // other stuff
})

.controller('Ctrl2',function($scope) {
  $scope.product = {description:'pump'};
  $scope.output = 'unknown';
  // uncomment to avoid undefined error,still can't see $pristine
  // $scope.formHolder = {};
  $scope.checkForm = function() {
    $scope.descriptionTest = $scope.product.description;
    if ($scope.formHolder.productForm.$pristine) {
      $scope.output = 'yes';
    }
    if ($scope.formHolder.productForm.$dirty) {
      $scope.output = 'no' 
    }
  }
});

html

<body ng-controller="MainCtrl">
    <div >
      <ng-include ng-controller="Ctrl2" src="'myForm.html'"></ng-include>
    </div>
  </body>

myForm.html

<form name="productForm" novalidate>
  <h2>myForm</h2>
  description: <input type="text" name="description" ng-model="product.description"/>
  <br>
  <button ng-click="checkForm()">Check Form</button>
  <br>
  Form Pristine: {{output}}
  <br><br>
  I can see the description: {{descriptionTest}}
</form>

plunkr

问题是我的Ctrl2看不到productForm。起初我以为这跟原子继承ng-include做一个子范围有关,所以我尝试在Ctrl2中添加一个变量:

$scope.productForm = {};

这摆脱了错误,但是我的控制器仍然没有正确看到$ pristine或$ dirty。

我终于通过在productForm上方添加一个$ scope.formHolder对象来实现它:

plunkr

.controller('Ctrl2',still can't see $pristine
  $scope.formHolder = {};
  $scope.checkForm = function() {
    $scope.descriptionTest = $scope.product.description;
    if ($scope.formHolder.productForm.$pristine) {
      $scope.output = 'yes';
    }
    if ($scope.formHolder.productForm.$dirty) {
      $scope.output = 'no' 
    }
  }
});

html

<form name="formHolder.productForm" novalidate>

为什么这个工作?有没有更好的方法来做到这一点?

我这样结束了,因为我有一个工作表格&我想在其他地方重复使用的控制器/模板。我应该做一个指令,但除了表单的$原始和$脏特征之外,一切都正常工作,所有的ng模型var都被正确传递。

How can I set a form contained inside a ng-include to be prestine?有一个答案,“打破所有的规则”,但似乎更复杂。

当我写什么时候,表单Controller将$ pristine添加到作用域,并且到什么范围?

编辑/回答:

我的原始问题可以归结为关于表单指令如何写入范围的混淆。我有一个印象,它会采取的事情

<form name="productForm">...

并添加属性,如

$scope.productForm.$pristine = function() {...}

然而,它直接写在productForm之上:

$scope.productForm = formObject;

因此,窗体对象存储在Child中,而不是父选择答案中所述。

帮助我的小孩范围继承中的关键块是在阅读时咨询链,而不是写作。所以如果你设置的东西像childScope.myThing.property =’123’,而它看起来像一个写入,它首先必须做一个读取,以找出myThing是什么。而设置childScope.myThing =’567’是一个直接写入,并且不涉及查看父链。这更好地解释在:What are the nuances of scope prototypal / prototypical inheritance in AngularJS?

要理解为什么formHolder的解决方案工作,你必须先了解 JavaScript prototypes chain。我们来说明在下面的伪代码中没有formHolder的第一种情况:
$parentScope = {
  //I'm a parent scope inside Ctrl2
  productForm:{} //to avoid undefined reference error 
}

$childScope = {
  //I'm a child scope created by by ng-include 
  __protototype__: $parentScope 
}

当form指令被解析时,它会创建FormController,它在$ scope属性上设置在name属性值下的key。这几乎相当于:

$childScope.productForm = $formCtrl;

之后,2个示波器看起来像这样:

$parentScope = {
  //I'm a parent scope inside Ctrl2
  productForm:{} //to avoid undefined reference error 
}

$childScope = {
  //I'm a child scope created by by ng-include 
  productForm: $formCtrl

  __protototype__: $parentScope 
}

所以你实际上最终得到了两个不同对象的属性。
现在在第二种情况下,您有以下情况:

$parentScope = {
  //I'm a parent scope inside Ctrl2
  formHolder:{} //to avoid undefined reference error 
}

$childScope = {
  //I'm a child scope created by by ng-include 
  __protototype__: $parentScope 
}

当form指令在$ scope上设置FormController实例时,它使用不同的属性链:

$childScope.formHolder.productForm = $formCtrl;

这相当于写作:

var formHolder = $childScope.formHolder; //since formHolder isn't defined on $childScope
//the JS runtime will look for it in the prototypes chain and find it inside $parentScope
//so here formHolder is the very same object you created and set on $parentScope
formHolder.productForm = $formCtrl;

希望它有助于了解为什么第二个选项可行。至于您的第二部分问题 – 您的解决方案是简单而且完全可行的 – 但还有其他几种方法可以处理,这最好取决于实际的使用情况:

>使用没有子范围的指令来提取常见的标记和功能的一部分
>使用具有子范围的指令,通过直接父范围属性访问或通过发出的事件来传达状态更改
>使用不会创建子范围的custom include directive

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读