同一页面上的多个表单使用相同的指令和元素指令中的一个表单
Multiple forms on same page using same directive AND one form inside an element directive
背景: 我正在尝试创建一个 "halt navigation if form is dirty" 指令。我在 SO 上查看了几个 questions/examples 并且我将一些功能放在一起,但不太正确。我正在尝试将此指令用作整个 Web 应用程序中多个表单的属性。
问题: 我的页面包含两个嵌套在 [=13] 中的 <form>
元素("form1" 和 "form2") =] 元素。 Form2 进一步嵌套在自定义元素指令中。
当任一表单变脏并且我尝试导航到另一个页面(UI 路由器更改)时,我从我们的提示服务中获得了预期的自定义提示。但是,如果我尝试重新加载页面,我只会在 form2 变脏时收到浏览器生成的提示。 form1脏了没有提示
有人可以指导我如何在 form1 脏并且有 window 事件(例如重新加载)时生成浏览器提示吗?
相关 HTML
<!-- "main" view -->
<tabset>
<tab heading="Heading1">
<form name="FORM1" class="form-horizontal" form-dirty>
<!-- FORM STUFF -->
</form>
</tab>
<tab heading="Heading2">
<this-contains-form2 data="objOnScope"></this-contains-form2>
</tab>
</tabset>
<!-- "thisContainsForm2" template -->
<form name="FORM2" class="form-horizontal" form-dirty>
<!-- FORM STUFF -->
</form>
相关 JAVASCRIPT
// "form-dirty" directive
angular.module('webapp.shared').directive('formDirty', ['$state', 'DlgPromptService', function($state, DlgPromptService) {
return {
scope: {theForm: '=name'},
restrict: 'A',
link: function (scope, element, attrs) {
scope.$watch('theForm', function () {
// if there's a UI router change
scope.$on('$stateChangeStart', function (event, toState, toParams){
// WHEN FORM1 DIRTY: PROMPT AND CONSOLE-LOG BOTH FORMS
// WHEN FORM2 DIRTY: PROMPT AND CONSOLE-LOG BOTH FORMS
console.log(scope.theForm);
// if form was not modified
if ( !scope.theForm.$dirty ) {
return;
}
else {
// if form was modified then intervene
// halt the route change
event.preventDefault();
// prompt user
DlgPromptService.confirm('Unsaved Changes',
'This form has unsaved changes.<br/>'
+'Are you sure you want to leave?')
.then(function () {
// we will proceed with the route change
scope.theForm.$setPristine();
$state.go(toState.name, toParams);
})
}
})
// if there's a window change (reload, etc)
window.onbeforeunload = function (event) {
// WHEN FORM1 DIRTY: NO PROMPT, NO CONSOLE LOG
// WHEN FORM2 DIRTY: PROMPT AND CONSOLE-LOG FORM2
console.log(scope.theForm);
// if form was not modified
if ( !scope.theForm.$dirty ) {
return;
}
else {
// prompt
return "prompt";
}
}
scope.$on('$destroy', function() {
window.onbeforeunload = undefined;
})
})
}
}
}])
// "thisContainsForm2" directive
angular.module('webapp.shared').directive('thisContainsForm2', function() {
var controller = function($scope, $http, $state, DlgPromptService) {
// CONTROLLER STUFF
}
return {
scope : {data: '='},
templateUrl : 'shared/thisContainsForm2.html',
controller : controller
}
})
如果您使用 ui bootstraps 选项卡实现,您必须注意始终呈现所有选项卡,但所有非活动选项卡都设置为 'display: none'
在这种情况下,两个 form-dirty 指令同时处于活动状态,这是一个问题,因为第二个选项卡会覆盖第一个选项卡 window.onbeforeunload function
为此使用 jQuerys 事件机制能够注册多个此类侦听器或编写您自己的解决方案
如果您只是在同一页上将两个表单放在彼此下方,则问题也可能存在 -> 在卸载之前只有第二个表单会被正确处理
背景: 我正在尝试创建一个 "halt navigation if form is dirty" 指令。我在 SO 上查看了几个 questions/examples 并且我将一些功能放在一起,但不太正确。我正在尝试将此指令用作整个 Web 应用程序中多个表单的属性。
问题: 我的页面包含两个嵌套在 [=13] 中的 <form>
元素("form1" 和 "form2") =] 元素。 Form2 进一步嵌套在自定义元素指令中。
当任一表单变脏并且我尝试导航到另一个页面(UI 路由器更改)时,我从我们的提示服务中获得了预期的自定义提示。但是,如果我尝试重新加载页面,我只会在 form2 变脏时收到浏览器生成的提示。 form1脏了没有提示
有人可以指导我如何在 form1 脏并且有 window 事件(例如重新加载)时生成浏览器提示吗?
相关 HTML
<!-- "main" view -->
<tabset>
<tab heading="Heading1">
<form name="FORM1" class="form-horizontal" form-dirty>
<!-- FORM STUFF -->
</form>
</tab>
<tab heading="Heading2">
<this-contains-form2 data="objOnScope"></this-contains-form2>
</tab>
</tabset>
<!-- "thisContainsForm2" template -->
<form name="FORM2" class="form-horizontal" form-dirty>
<!-- FORM STUFF -->
</form>
相关 JAVASCRIPT
// "form-dirty" directive
angular.module('webapp.shared').directive('formDirty', ['$state', 'DlgPromptService', function($state, DlgPromptService) {
return {
scope: {theForm: '=name'},
restrict: 'A',
link: function (scope, element, attrs) {
scope.$watch('theForm', function () {
// if there's a UI router change
scope.$on('$stateChangeStart', function (event, toState, toParams){
// WHEN FORM1 DIRTY: PROMPT AND CONSOLE-LOG BOTH FORMS
// WHEN FORM2 DIRTY: PROMPT AND CONSOLE-LOG BOTH FORMS
console.log(scope.theForm);
// if form was not modified
if ( !scope.theForm.$dirty ) {
return;
}
else {
// if form was modified then intervene
// halt the route change
event.preventDefault();
// prompt user
DlgPromptService.confirm('Unsaved Changes',
'This form has unsaved changes.<br/>'
+'Are you sure you want to leave?')
.then(function () {
// we will proceed with the route change
scope.theForm.$setPristine();
$state.go(toState.name, toParams);
})
}
})
// if there's a window change (reload, etc)
window.onbeforeunload = function (event) {
// WHEN FORM1 DIRTY: NO PROMPT, NO CONSOLE LOG
// WHEN FORM2 DIRTY: PROMPT AND CONSOLE-LOG FORM2
console.log(scope.theForm);
// if form was not modified
if ( !scope.theForm.$dirty ) {
return;
}
else {
// prompt
return "prompt";
}
}
scope.$on('$destroy', function() {
window.onbeforeunload = undefined;
})
})
}
}
}])
// "thisContainsForm2" directive
angular.module('webapp.shared').directive('thisContainsForm2', function() {
var controller = function($scope, $http, $state, DlgPromptService) {
// CONTROLLER STUFF
}
return {
scope : {data: '='},
templateUrl : 'shared/thisContainsForm2.html',
controller : controller
}
})
如果您使用 ui bootstraps 选项卡实现,您必须注意始终呈现所有选项卡,但所有非活动选项卡都设置为 'display: none'
在这种情况下,两个 form-dirty 指令同时处于活动状态,这是一个问题,因为第二个选项卡会覆盖第一个选项卡 window.onbeforeunload function
为此使用 jQuerys 事件机制能够注册多个此类侦听器或编写您自己的解决方案
如果您只是在同一页上将两个表单放在彼此下方,则问题也可能存在 -> 在卸载之前只有第二个表单会被正确处理