I have a main form with the following markup
<tabset vertical="true" type="pills">
<tab ng-repeat="tab in tabsViews" select="selectView(tab.name, tab.index)"
ng-show="tab.isVisible"
class=" {{tabsViews[tab.index-1]['invalid'] ? 'invalid-tab': 'valid-tab' }}">
<tab-heading>{{tab.title}}</tab-heading>
</tab>
</tabset>
and the selectView method in my controller is the following:
$scope.previousIndex = null;
$scope.selectView = function (viewName, viewIndex) {
$scope.selections.showInvoicesDetailView = false;
$scope.selections.showInvoicesView = false;
$scope.selections.showPassesView = false;
if (viewIndex) {
if ($scope.previousIndex != null && $scope.form) {
$scope.tabsViews[$scope.previousIndex - 1]["invalid"] = $scope.form.$invalid;
}
$scope.previousIndex = viewIndex;
}
if (viewName.substring(0, 9) != 'invoices.')
$scope.selections.lastSelectedView = viewName;
else
$scope.selections.showInvoicesDetailView = true;
if (viewName == 'guestPasses')
$scope.selections.showPassesView = true;
if (viewName == 'invoices')
$scope.selections.showInvoicesView = true;
if ($scope.selections.isNew) {
window.console && console.log('SelectView called with the new.' + viewName + ' view...');
$state.go('new.' + viewName);
}
else {
window.console && console.log('SelectView called with the edit.' + viewName + ' view...');
$state.go('edit.' + viewName);
}
};
The main form has a directive to detect its dirty state and ask for saving the changes. The problem is that when I change anything in my current view, that form's dirty state is not propagated into that main form. Is there a way to set main form dirty state based on the particular tab (defined as the view) dirty state?
To understand the problem better, here is the main form markup (the one that has tabs):
div ng-class="{'col-md-7': $parent.showSearch, 'col-md-11': !$parent.showSearch}">
@Html.Partial("_EditFormHeader")
<div class="fourpanel">
<div data-sm:collapse="$parent.showForm" id="hideFrm" class="pull-left col-sm-3 sm-search-list">
<form name="guestMainForm" novalidate role="form" data-sm:dirty-check data-server:error
ng-show="$parent.showForm && !selections.justDeleted" class="ng-cloak">
<div id="guestEditForm" class="widget" data-resize:container>
<div class="widget-head">
<div class="row">
<div class="clearfix"></div>
@Labels.guest: {{currentGuest.contactPerson.firstName + ' ' + currentGuest.contactPerson.lastName}} {{ !isNew ? '(' + currentGuest.guestNo + ')' : '' }}
<div class="pull-right text-right col-lg-1" style="padding-right:5px">
<i class="fa fa-angle-double-left sm-slider-button" ng-click="toggleFormVisibility()"
alt="@String.Format(Labels.hideX, Labels.account)" id="angle-left"></i>
</div>
</div>
</div>
<div class="widget-content">
<div class="scrollable widget-resize">
<div class="padd">
@Html.Partial("_EditFormAlerts")
</div>
<div class="col-lg-2 col-md-2 panel-container">
<tabset vertical="true" type="pills">
<tab ng-repeat="tab in tabsViews" select="selectView(tab.name, tab.index)"
ng-show="tab.isVisible"
class=" {{tabsViews[tab.index-1]['invalid'] ? 'invalid-tab': 'valid-tab' }}">
<tab-heading>{{tab.title}}</tab-heading>
</tab>
</tabset>
</div>
<div class="col-lg-8 col-md-4 panel-container">
<div data-ui-view data-autoscroll="false"></div>
<div data-ui-view="guestPasses" ng-show="selections.showPassesView"></div>
<div data-ui-view="invoices" data-autoscroll="false" ng-show="selections.showInvoicesView"></div>
</div>
</div>
</div>
<div class="widget-foot">
<div ng-show="!isNew">
<button class="btn btn-primary" ng-click="save(currentGuest)"
ng-disabled="form.$invalid || disableAction">
@Labels.save
</button>
<data-delete:button title="{{ '@Labels.delete: ' + currentGuest.contactPerson.firstName.trim() + ' ' + currentGuest.contactPerson.lastName.trim() + ' (' + currentGuest.guestNo +')' }}"
message="@String.Format(Messages.confirmDelete, Labels.guest)"
disable-action="disableAction"
delete="delete()">
</data-delete:button>
<data-cancel:button title="@Labels.unsavedChanges"
message="@Messages.unsavedChanges"
cancel="cancel()"
disable-action="disableAction"
dirty="form.$dirty">
</data-cancel:button>
</div>
<div ng-show="isNew">
<button id="btnAdd" class="btn btn-primary" ng-click="new(currentGuest)"
ng-disabled="form.$invalid || disableAction">
@Labels.add
</button>
<data-cancel:button title="@Labels.unsavedChanges"
message="@Messages.unsavedChanges"
cancel="cancel()"
disable-action="disableAction"
dirty="form.$dirty">
</data-cancel:button>
</div>
</div>
</div>
</form>
</div>
<div id="showFrm" class="sm-form-expand-button text-center col-sm-1"
ng-show="!$parent.showForm"
ng-click="toggleFormVisibility()">
<i class="fa fa-angle-double-right"></i>
<div class="panel2Label">@Labels.guest: {{ currentGuest.contact.firstName.trim() + ' ' + currentGuest.contact.lastName.trim() }} {{ !isNew ? '(' + currentGuest.guestNo + ')' : '' }}</div>
</div>
<div class="col-sm-5 panel-container">
<div data-ui-view="detail" data-autoscroll="true" ng-show="selections.showInvoicesDetailView"></div>
<div data-ui-view="passDetail"></div>
</div>
</div>
</div>
I created a new directive and added it to my view forms:
function ($modal, $rootScope, $location, $state) {
return {
restrict: 'A',
require: ['^form'],
//scope: {
// onOk: '&',
// onCancel: '&'
//},
link: function (scope, element, attrs, controllers) {
var form = controllers[0];
window.console && console.log(form);
window.onbeforeunload = function () {
if ((form && form.$dirty) || element.hasClass('ng-dirty')) {
// return resourceFactory.getResource('Messages', 'unsavedChanges');
if (scope.form)
{
scope.form.$setDirty();
}
}
};
}
};
I am debugging and I can see that form is correctly set to my view's form and I can access the parent form using form.$$parentForm property. However, I don't know to which event should I hook to set form.$$parentForm.$setDirty when my form becomes dirty. If you can help me figure this out, then it will work for me, I guess.