我的未保存更改指令需要适用于所有具有不同名称的表单
My unsaved changes directive needs to work for all forms with different names
我有一个指令可以打开一个模式来提醒用户未保存的更改,我需要它来检查具有不同未知名称的脏表单。我曾尝试使用范围来访问表单名称和 this 但没有成功。我可以使用 elem[0].name 访问表单名称,但它不带有 $dirty value.
形式
<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;
}
}
};
}]);
尝试使用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);
}
};
});
<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>
我建议创建一个用于观察路线变化的服务,您可以在其中注册您想要 spy 的所有表格。表格的注册将由您的指令处理。
我在下面整理了一些代码:
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;
});
我无法对其进行测试,因此它可能包含一些小错误 - 请告诉我,我会检查。另请注意,我的代码是 而不是 缩小保存!
我有一个指令可以打开一个模式来提醒用户未保存的更改,我需要它来检查具有不同未知名称的脏表单。我曾尝试使用范围来访问表单名称和 this 但没有成功。我可以使用 elem[0].name 访问表单名称,但它不带有 $dirty value.
形式<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;
}
}
};
}]);
尝试使用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);
}
};
});
<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>
我建议创建一个用于观察路线变化的服务,您可以在其中注册您想要 spy 的所有表格。表格的注册将由您的指令处理。
我在下面整理了一些代码:
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;
});
我无法对其进行测试,因此它可能包含一些小错误 - 请告诉我,我会检查。另请注意,我的代码是 而不是 缩小保存!