</ng-template>
<eg-batch-item-attr label="{{cat.name()}} ({{orgSn(cat.owner())}})" i18n-label
name="stat_cat_{{cat.id()}}" editInputDomId="stat-cat-input-{{cat.id()}}"
+ [valueRequired]="cat.required() == 't'"
[editTemplate]="statCatTemplate"
[labelCounts]="statCatCounts(cat.id())"
(valueCleared)="statCatChanged(cat.id(), true)"
beforeTabChange(evt: NgbNavChangeEvent) {
evt.preventDefault();
- let promise = this.canDeactivate();
- if (!(promise instanceof Promise)) {
- promise = Promise.resolve(promise);
- }
-
- promise.then(ok => {
- if (ok) {
- this.routingAllowed = true;
- this.tab = evt.nextId;
- this.routeToTab();
- }
- });
+ // Always allow routing between tabs since no changes are lost
+ // in the process. In some cases, this is necessary to avoid
+ // "pending changes" alerts while you are trying to resolve
+ // other issues (e.g. applying values for required fields).
+ this.routingAllowed = true;
+ this.tab = evt.nextId;
+ this.routeToTab();
}
routeToTab() {
}
isNotSaveable(): boolean {
- return !(this.volsCanSave && this.attrsCanSave);
+
+ if (!this.volsCanSave) { return true; }
+ if (!this.attrsCanSave) { return true; }
+
+ // This can happen regardless of whether we are modifying
+ // volumes vs. copies.
+ if (this.volcopy.missingRequiredStatCat()) { return true; }
+
+ return false;
}
volsCanSaveChange(can: boolean) {
return this.copyStatuses[statId] &&
this.copyStatuses[statId].restrict_copy_delete() === 't';
}
+
+ // Returns true if any items are missing values for a required stat cat.
+ missingRequiredStatCat(): boolean {
+ let missing = false;
+
+ this.currentContext.copyList().forEach(copy => {
+ if (!copy.barcode()) { return; }
+
+ this.commonData.acp_stat_cat.forEach(cat => {
+ if (cat.required() !== 't') { return; }
+
+ const matches = copy.stat_cat_entries()
+ .filter(e => e.stat_cat() === cat.id());
+
+ if (matches.length === 0) {
+ missing = true;
+ }
+ });
+ });
+
+ return missing;
+ }
}