我有一个指令打开一个模式来提醒用户未保存的更改,我需要它来检查具有不同未知名称的脏表单。我曾尝试使用范围访问表单名称和此,但尚未成功。我可以使用elem [0] .name访问表单名称,但它不带有$ dirty值。
<form class="form-inline" role="form" name="myFormName" confirm-on-exit>
Cool form html
</form>
app.directive('confirmOnExit', ['modalService', '$rootScope', '$stateParams', '$state', function (modalService, $rootScope, $stateParms, $state) {
return {
restrict: 'A',
link: function (scope, elem, attrs, formCtrl) {
onRouteChangeOff = $rootScope.$on('$stateChangeStart', routeChange);
function routeChange(event, newState, newParams, fromState, fromParams) {
if (scope.myFormName.$dirty) {
return;
}
event.preventDefault();
var modalOptions = {
closeButtonText: 'No, I\'ll stay and save them.',
actionButtonText: 'Yes, Leave and Ignore Changes',
headerText: 'Unsaved Changes',
bodyText: 'You have unsaved changes. Do you want to leave the page?'
};
modalService.showModal({}, modalOptions).then(function (result) {
if (result) {
onRouteChangeOff(); //Stop listening for location changes
$state.go(newState); //Go to page they're interested in
} else {
$state.go(fromState); //Stay on the page and have tab revert to fromState
}
});
return;
}
}
};
}]);
答案 0 :(得分:2)
我建议您创建一个服务来观察路线变化,您可以在其中注册要间谍的所有表格。然后,您的指令将处理表格的注册。
我在下面汇总了一些代码:
app.directive('confirmOnExit', function (FormChanges) {
return {
restrict: 'A',
link: function (scope, elem, attrs, formCtrl) {
FormChanges.register(scope, attrs.name);
}
};
}]);
app.factory('FormChanges', function (modalService, $rootScope, $state) {
var formNames = [];
var dirtyCallbacks = {};
$rootScope.$on('$stateChangeStart', function (event, newState, newParams, fromState, fromParams) {
var hasDirtyForm = false;
// Check all registered forms if any of them is dirty
for (var i = 0; i < formNames.length; i++) {
var name = formNames[i];
if (dirtyCallbacks[name] && dirtyCallbacks[name]()) {
// got a dirty form!
hasDirtyForm = true;
break;
}
}
if (!hasDirtyForm) {
// Nothing is dirty, we can continue normally
return;
}
// Something was dirty, show modal
event.preventDefault();
var modalOptions = {
closeButtonText: 'No, I\'ll stay and save them.',
actionButtonText: 'Yes, Leave and Ignore Changes',
headerText: 'Unsaved Changes',
bodyText: 'You have unsaved changes. Do you want to leave the page?'
};
modalService.showModal({}, modalOptions).then(function (result) {
if (result) {
// clear the current forms
formNames = [];
dirtyCallbacks = {};
$state.go(newState, newParams); //Go to page they're interested in
} else {
$state.go(fromState, fromParams); //Stay on the page and have tab revert to fromState
}
});
return;
});
$rootScope.$on('$stateChangeSuccess', function () {
// be sure to clear the registered forms when change was successful
formNames = [];
dirtyCallbacks = {};
});
var service = {
// Register a form by giving the scope it's contained in and its name
register: function (scope, name) {
scope.$on('$destroy', function () {
// e.g. an ng-if may destroy the scope, so make sure to remove this form again
service.remove(name);
});
formNames.push(name);
dirtyCallbacks[name] = function () {
return scope[name].$dirty;
};
},
remove: function (name) {
delete dirtyCallbacks[name];
}
};
return service;
});
我无法测试它,所以它可能包含一些小错误 - 只是让我知道,我会检查。另请注意,我的代码不缩小保存!
答案 1 :(得分:1)
尝试使用scope.$eval(attrs.name)
获取与name属性中的名称关联的变量。它的行为应该与普通的范围变量一样,您应该能够访问它的所有属性。
此代码段显示检查$dirty
有效:
angular.module('test', [])
.directive('testdirective', function () {
return {
restrict: 'A',
link: function (scope, elem, attrs, formCtrl) {
console.log(scope.$eval(attrs.name), scope.$eval(attrs.name).$dirty);
}
};
});
&#13;
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
Open Console
<div ng-app="test">
<form testdirective name="testform"></form>
</div>
&#13;