Подтвердить что ты не робот

Как я могу установить форму, содержащуюся внутри ng-include, чтобы быть престижным?

У меня есть следующий код:

<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 я пытаюсь использовать следующий код для reset для формы:

$scope.itemForm.$setPristine();

Когда я это делаю, он говорит мне, что "itemForm" undefined.

Есть ли способ, которым я могу установить содержимое формы в нетронутую. Я предполагаю, что это проблема с областью, но я не уверен, как ее исправить. я попробовал одно решение по удалению второго включить и вставить код непосредственно. Это решение работает.

Однако мы хотим иметь возможность повторно использовать код поэтому я хотел бы иметь возможность сделать это с помощью include для 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 и хотим установить его в $netist от кнопки внутри.

4b9b3361

Ответ 1

Этот ответ нарушит все правила (т.е. обход 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, а затем из $element, где определен AdminController, мы ищем элементы form, выбираем первый, а затем получаем его FormController.

Plunker

Если вы вызываете $setPristine() только в результате взаимодействия с пользователем, вам не нужно искать событие $includedContentLoaded – Я только должен был сделать это, потому что я не хотел создавать какой-либо компонент пользовательского интерфейса для запуска операции, и когда контроллер сначала запускается, форма еще не существует.

См. также AngularJS: Access formController формы, помещенной внутри transcluded директивы от родительского контроллера, которая касается аналогичной проблемы с попыткой доступа к дочернию из родителя.

Более чистое решение: определите директиву (используйте ее в элементе ng-include) и передайте ей функцию AdminController в качестве атрибута. В функции директивной ссылки вызовите этот метод и передайте FormController в качестве параметра. Тогда AdminController будет иметь ссылку на желаемый FormController. (Я не стал это кодировать, так как я не уверен, что вы хотите получить решение, в котором вы должны использовать директиву вместе с ng-include.)

Ответ 2

Ну, один из способов сделать это - трансляция события, например:

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.

Ответ 3

Не нарушайте правила:) Просто определите переменную (пустой объект) в контроллере и используйте ее при определении формы. Поскольку angular JS использует прототипы прототипов под капотом, когда форма попытается получить доступ к внутренней области (для начальной загрузки переменной), она сначала будет проходить через цепочку видимости и попытаться найти ту же переменную в родительской области.

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

Ссылка для справки http://blog.152.org/2014/07/angular-form-element-not-attaching-to.html

Ответ 4

Если вы хотите достичь этого в результате некоторого взаимодействия с пользователем, на мой взгляд, гораздо более чистым и "angular" способом было бы использовать пользовательскую директиву, которая установит форму в нетронутую (т.е. когда пользователь хочет очистить форму, нажав 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
                });
              };
            }
  };

Смотрите plunk