проверить несохраненные данные формы в angularjs (несколько форм с использованием ui-router)

Детали реализации:

Я использую ui-router для загрузки страницы формы в ui-view div. Я сослался на отличный пример Andres Ekdahi, как я могу это сделать? $грязная проверка нескольких форм с использованием одной и той же директивы?

форма1

 <form name="myForm" ng-controller="Controller" confirm-on-exit>

форма2

<form name="iForm" ng-controller="Controller" confirm-on-exit ng-model="myModel">

app.js (директива)

myApp.directive('confirmOnExit', function() {
        return {
            link: function($scope, elem, attrs) {
                // condition when back page is pressed 
                window.onbeforeunload = function(){
                    if ($scope.myForm.$dirty) {
                        return "The formI is dirty, do you want to stay on the page?";
                    }
                }
                // condition when user try to load other form (via icons )
                $scope.$on('$stateChangeStart', function(event, next, current) {
                    if ($scope.myForm.$dirty) {
                        if(!confirm("myForm. Do you want to continue ?")) {
                            event.preventDefault();
                        }
                    }

                    if ($scope.iForm.$dirty) {
                        if(!confirm("iform. Do you want to continue ?")) {
                            event.preventDefault();
                        }
                    }
                });
            }
        };
    });

Ошибка:

При первой загрузке страницы значение $dirty равно false. и я заполняю данные формы и нажимаю третий значок (файл), и я получаю сообщение об ошибке для грязной проверки второй формы if ($scope.iForm.$dirty) и для $dirty в предупреждении.

angular.js:12520 TypeError: Cannot read property '$dirty' of undefined

и

<form name="iForm" ng-controller="Controller" confirm-on-exit="" ng-model="myModel" class="ng-pristine ng-untouched ng-valid ng-scope">

Демо: Plunker




Ответы (3)


Упростите свою директиву, взяв ее из атрибута name атрибута form, так что внутри директивы будет лежать только одно условие, и ее можно будет повторно использовать во многих местах.

<form name="myForm" ng-controller="Controller" confirm-on-exit>

Код

var form = $scope[attrs.name]; //which will take out form name & do search that inside scope
if (form.$dirty) { //form object would always exist, to make sure you could also add one more check `form &&`
    if(!confirm("myForm. Do you want to continue ?")) {
        event.preventDefault();
    }
}

Демо здесь

person Pankaj Parkar    schedule 28.03.2016
comment
Можете ли вы объяснить мне, что ищет $scope[attrs.name]? это относится только к изменению данных формы или любому клику пользователя? - person Mad-D; 29.03.2016
comment
@Mad-D, который выберет имя формы и будет искать formName внутри области действия контроллера. - person Pankaj Parkar; 29.03.2016
comment
Спасибо, сэр, я думаю, это именно то, что мне нужно было сделать. - person Mad-D; 29.03.2016
comment
Не называйте меня сэром, я такой же, как вы. Рад помочь вам. Спасибо ;) - person Pankaj Parkar; 29.03.2016

Есть более простой способ.

Просто потребуйте, чтобы ваша директива была помещена в элемент формы, и получите доступ к контроллеру формы через функцию ссылки:

myApp.directive('confirmOnExit', function() {
        return {
            require: 'form',
            link: function($scope, elem, attrs, formController) {
                // condition when back page is pressed 
                window.onbeforeunload = function(){
                    if (formController.$dirty) {
                        return "The form '" + formController.$name + "' is dirty, do you want to stay on the page?";
                    }
                }
                // condition when user try to load other form (via icons )
                $scope.$on('$stateChangeStart', function(event, next, current) {
                    if (formController.$dirty) {
                        if(!confirm(formController.$name + ". Do you want to continue ?")) {
                            event.preventDefault();
                        }
                    }
                });
            }
        };
    });
person JC Ford    schedule 28.03.2016

проверьте, существует ли форма, прежде чем проверять, не загрязнена ли она. Сделайте что-нибудь вроде

if ($scope.myForm && $scope.myForm.$dirty) {
    if(!confirm("myForm. Do you want to continue ?")) {
        event.preventDefault();
    }
}

if ($scope.iForm && $scope.iForm.$dirty) {
    if(!confirm("iform. Do you want to continue ?")) {
        event.preventDefault();
    }
}
person holtc    schedule 28.03.2016
comment
спасибо, ваш ответ тоже правильный. Мне просто нужно было проверить существование формы. - person Mad-D; 29.03.2016