How can I set a form contained inside a ng-include to be prestine?

后端 未结 4 1095
轻奢々
轻奢々 2021-01-07 23:33

I have the following code:

相关标签:
4条回答
  • 2021-01-07 23:51

    Do not break the rules :) Just define the variable (empty object) in the controller and use it while defining your form. Since angular JS uses scope prototypes under the hood, when form will try to access the inner scope (to bootstrap the variable), it will first go via scope chain and try to find the same variable in the parent's scope.

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

    Link for reference http://blog.152.org/2014/07/angular-form-element-not-attaching-to.html

    0 讨论(0)
  • 2021-01-07 23:54

    Well, one way to do it is to broadcast an event, like so:

    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();
            });
        });
    

    This way you don't have to traverse the dom.

    0 讨论(0)
  • 2021-01-07 23:59

    This answer will break all the rules (i.e., DOM traversal inside a controller), but here it is anyway...

    .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();
      });
    }]);
    

    We wait for the ng-included content to load, then from the $element where AdminController is defined, we look for form elements, pick the first one, then get its FormController.

    Plunker

    If you are only calling $setPristine() as a result of some user interaction, you won't need to look for the $includedContentLoaded event – I only had to do that because I didn't want to create any UI component to trigger the operation, and when the controller first runs, the form doesn't exist yet.

    See also AngularJS: Access formController of a form placed inside transcluded directive from parent controller which deals with the similar problem of trying to access a child from a parent.

    A cleaner solution: define a directive (use it on the ng-include element) and pass it an AdminController function as an attribute. In the directive's link function, call that method and pass the FormController as a parameter. Then the AdminController will have a reference to the desired FormController. (I did not bother coding this up, as I'm not sure you want a solution where you have to use a directive along with ng-include.)

    0 讨论(0)
  • 2021-01-08 00:12

    If you want to achieve this as the result of some user interaction, in my opinion a much more cleaner and 'angular' way of doing it would be to use a custom directive which will set the form to pristine (i.e. when the user wants to clear the form by pressing esc or clicking a button or whatever).

    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();
                  };
                }
      };
    });
    

    and simply hook it up to some button in your form:

    <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>
    

    And if you're looking to set the form to pristine directly from the controller, (not as a result of some user interaction) such as success response from a POST, then one way would be to assign a callback to the directive which will be responsible for clearing the form and then invoking that callback from the controller. In your view:

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

    and the controller:

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

    and the directive:

    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
                    });
                  };
                }
      };
    

    See plunk

    0 讨论(0)
提交回复
热议问题