16

我有以下代码:

<div modal="modal.shouldBeOpen" close="close()" options="opts">
    <div class="modal-body">
        <form novalidate name="itemForm" style="margin-bottom: 0px;">

包含在包含的文件 modal.html 中

<div data-ng-controller="AdminController">
   <ng-include src="'/Content/app/admin/partials/grid-subject.html'"></ng-include >
   <ng-include src="'/Content/app/admin/partials/modal.html'"></ng-include>
</div>

在我的 AdminController 控制器中,我尝试使用以下代码将表单重置为原始状态:

$scope.itemForm.$setPristine();

当我这样做时,它告诉我“itemForm”未定义。

有没有办法可以将表单的内容设置为原始内容。我认为这是一个范围问题,但我不知道如何解决它。我尝试了删除第二个包含并直接粘贴代码的一种解决方案。此解决方案有效。

但是我们希望能够重用代码,所以我希望能够通过包含 modal.html 来做到这一点

请注意,我们想要这样做的原因是因为我们的 modal.html 上有如下内容:

    <button
        class="btn float-right"
        data-ng-disabled="itemForm.$pristine"
        data-ng-click="modalReset()"
        data-ng-show="modal.resetButton">
        Reset</button>
</form>

所以我们实际上是在 itemForm 里面,并且想从里面的按钮将它设置为 $pristine。

4

4 回答 4

10

这个答案将打破所有规则(即,控制器内的 DOM 遍历),但无论如何......

.controller('AdminController', ['$scope','$element',
function($scope, $element) {
  $scope.$on('$includeContentLoaded', function() {
    var childFormController = $element.find('form').eq(0).controller('form');
    console.log(childFormController);
    childFormController.$setPristine();
  });
}]);

我们等待 ng-included 内容加载,然后从$element定义 AdminController 的位置查找form元素,选择第一个元素,然后获取其 FormController。

普朗克

如果您只是$setPristine()由于某些用户交互而调用,则不需要查找$includedContentLoaded事件——我只需要这样做是因为我不想创建任何 UI 组件来触发操作,并且当控制器第一次运行,表单还不存在。

另请参阅AngularJS: Access formController of a form from transcluded directive from parent controller处理尝试从父级访问子级的类似问题。

更简洁的解决方案:定义一个指令(在 n​​g-include 元素上使用它)并将 AdminController 函数作为属性传递给它。在指令的链接函数中,调用该方法并将 FormController 作为参数传递。然后 AdminController 将具有对所需 FormController 的引用。(我没有费心编写代码,因为我不确定您是否想要一个必须使用指令和 ng-include 的解决方案。)

于 2013-07-06T17:28:13.397 回答
4

好吧,一种方法是广播一个事件,如下所示:

angular.module('myApp',[])
    .controller('AdminCtrl',function($scope){
        $scope.modalReset = function(){
            $scope.$broadcast('modal-reset');
        };
    })
    .controller('ModalCtrl', function($scope){
        $scope.$on('modal-reset', function(){
            $scope.itemForm.$setPristine();
        });
    });

这样你就不必遍历 dom。

于 2013-07-09T13:29:36.650 回答
1

不要违反规则 :) 只需在控制器中定义变量(空对象)并在定义表单时使用它。由于 Angular JS 在后台使用作用域原型,当表单尝试访问内部作用域(引导变量)时,它将首先通过作用域链并尝试在父作用域中找到相同的变量。

<!—- The vars should live in the controller. I placed them here for the example. -—&gt;
<div ng-controller=“controllerName” ng-init="form={}; model={}" >
    <div ng-include=“ ‘path-to-the-template’ ”&gt;</div>
</div>

<!—- Inside path-to-the-template -—&gt;
<form name="form.createUser">
    <input name="name" ng-model="model.name" />
    <input name="email" ng-model="model.email" />
</form>

参考链接http://blog.152.org/2014/07/angular-form-element-not-attaching-to.html

于 2015-10-29T21:21:57.873 回答
0

如果您想通过一些用户交互来实现这一点,在我看来,一种更清洁和“角度”的方法是使用自定义指令,它将表单设置为原始(即当用户想要通过按 esc 或单击按钮或其他方式清除表单)。

app.directive("formCleaner",
  function () {
        return {
            restrict: 'E',
            require: '^form',
            scope: {
                callback: '&',
                defaultText:'@'
            },
            template: '<button type="button" ng-click="setFormToPristine()" class="btn btn-warning"  >{{defaultText}}</button>',
            link: function (scope, element, attrs, formCtrl) {
                scope.setFormToPristine = function () {
                    formCtrl.$setPristine();
                    scope.callback();
              };
            }
  };
});

并简单地将其连接到表单中的某个按钮:

<form name="testForm">
      <input type="text" ng-model="someModel" />
      <hr/>
      <input type="button" value="submit form" class="btn btn-primary" ng-disabled="testForm.$pristine" 
        ng-click=submitForm(testForm) />
      <form-cleaner callback="resetFormCallback(testForm)" default-text="Clear Form"></form-cleaner>
</form>

如果您希望直接从控制器将表单设置为原始状态(而不是由于某些用户交互),例如来自 POST 的成功响应,那么一种方法是将回调分配给指令,该指令将是负责清除表单,然后从控制器调用该回调。在您看来:

<form-cleaner callback="resetFormCallback(testForm)" default-text="Clear Form"></form-cleaner>

和控制器:

 $scope.resetFormOnSubmitCallback=function(cb){
    $log.warn("simulating $http POST call.....");
      $timeout(function() {
            cb();
            $scope.someModel=null;
        }, 3000)
  }

和指令:

return {
            restrict: 'E',
            require: '^form',
            scope: {
                callback: '&',
                defaultText:'@',
                ngDisabled:'='
            },
            template: '<button type="button" ng-disabled="ngDisabled" ng-click="submitForm()" class="btn btn-primary"  >{{defaultText}}</button>',

            link: function (scope, element, attrs, formCtrl) {
            var setFormToPristine=function(){
              $log.log("setting form to prsitine....");
              formCtrl.$setPristine();
            };  

                scope.submitForm = function () {
                scope.callback({
                    onFormSubmittedCallback:setFormToPristine
                });
              };
            }
  };

笨拙

于 2014-01-08T09:02:48.273 回答