Проверка несохраненных данных формы в angularjs (несколько форм с использованием ui-router)
Детали реализации:
Я использую UI-маршрутизатор для загрузки страницы формы в UI-View Div. Я привел замечательный пример Андрес Экдахи, Как я могу сделать грязную проверку на нескольких формах, используя одну и ту же директиву?
form1
<form name="myForm" ng-controller="Controller" confirm-on-exit>
form2
<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">
Демо: Плункер
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();
}
}
Есть более простой способ.
Просто потребуйте, чтобы ваша директива была помещена в элемент формы, и получите доступ к контроллеру формы через функцию ссылки:
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();
}
}
});
}
};
});
Проверьте, существует ли форма, прежде чем проверять, не загрязнена ли она. Сделать что-то вроде
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();
}
}