View Context: observe parent activation to make sure children follows along. (#20206)
observe parent activation to make sure children follows along.
This commit is contained in:
@@ -1,5 +1,10 @@
|
|||||||
import { UMB_VIEW_CONTEXT } from './view.context-token.js';
|
import { UMB_VIEW_CONTEXT } from './view.context-token.js';
|
||||||
import { UmbClassState, UmbStringState, mergeObservables } from '@umbraco-cms/backoffice/observable-api';
|
import {
|
||||||
|
UmbBooleanState,
|
||||||
|
UmbClassState,
|
||||||
|
UmbStringState,
|
||||||
|
mergeObservables,
|
||||||
|
} from '@umbraco-cms/backoffice/observable-api';
|
||||||
import { UmbControllerBase } from '@umbraco-cms/backoffice/class-api';
|
import { UmbControllerBase } from '@umbraco-cms/backoffice/class-api';
|
||||||
import { UmbHintController } from '@umbraco-cms/backoffice/hint';
|
import { UmbHintController } from '@umbraco-cms/backoffice/hint';
|
||||||
import { UmbLocalizationController } from '@umbraco-cms/backoffice/localization-api';
|
import { UmbLocalizationController } from '@umbraco-cms/backoffice/localization-api';
|
||||||
@@ -9,6 +14,8 @@ import type { UmbControllerHost } from '@umbraco-cms/backoffice/controller-api';
|
|||||||
import type { UmbVariantHint } from '@umbraco-cms/backoffice/hint';
|
import type { UmbVariantHint } from '@umbraco-cms/backoffice/hint';
|
||||||
import type { UmbVariantId } from '@umbraco-cms/backoffice/variant';
|
import type { UmbVariantId } from '@umbraco-cms/backoffice/variant';
|
||||||
|
|
||||||
|
const ObserveParentActiveCtrlAlias = Symbol();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* TODO:
|
* TODO:
|
||||||
@@ -30,7 +37,11 @@ export class UmbViewController extends UmbControllerBase {
|
|||||||
|
|
||||||
// State used to know if the context can be auto activated when attached.
|
// State used to know if the context can be auto activated when attached.
|
||||||
#autoActivate = true;
|
#autoActivate = true;
|
||||||
#active = false;
|
#active = new UmbBooleanState(false);
|
||||||
|
public readonly active = this.#active.asObservable();
|
||||||
|
get isActive() {
|
||||||
|
return this.#active.getValue();
|
||||||
|
}
|
||||||
#hasActiveChild = false;
|
#hasActiveChild = false;
|
||||||
#inherit?: boolean;
|
#inherit?: boolean;
|
||||||
#explicitInheritance?: boolean;
|
#explicitInheritance?: boolean;
|
||||||
@@ -68,11 +79,11 @@ export class UmbViewController extends UmbControllerBase {
|
|||||||
this.#consumeParentCtrl = this.consumeContext(UMB_VIEW_CONTEXT, (parentView) => {
|
this.#consumeParentCtrl = this.consumeContext(UMB_VIEW_CONTEXT, (parentView) => {
|
||||||
// In case of explicit inheritance we do not want to overview the parent view.
|
// In case of explicit inheritance we do not want to overview the parent view.
|
||||||
if (this.#explicitInheritance) return;
|
if (this.#explicitInheritance) return;
|
||||||
if (this.#active && !this.#hasActiveChild) {
|
if (this.isActive && !this.#hasActiveChild) {
|
||||||
// If we were active we will react as if we got deactivated and then activated again below if state allows. [NL]
|
// If we were active we will react as if we got deactivated and then activated again below if state allows. [NL]
|
||||||
this.#propagateActivation();
|
this.#propagateActivation();
|
||||||
}
|
}
|
||||||
this.#active = false;
|
this.#active.setValue(false);
|
||||||
if (parentView) {
|
if (parentView) {
|
||||||
this.#parentView = parentView;
|
this.#parentView = parentView;
|
||||||
}
|
}
|
||||||
@@ -125,22 +136,23 @@ export class UmbViewController extends UmbControllerBase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
override hostConnected(): void {
|
override hostConnected(): void {
|
||||||
|
const wasActive = this.isActive;
|
||||||
this.#attached = true;
|
this.#attached = true;
|
||||||
super.hostConnected();
|
super.hostConnected();
|
||||||
// CHeck that we have a providerController, otherwise this is not provided. [NL]
|
// Check that we have a providerController, otherwise this is not provided. [NL]
|
||||||
if (this.#autoActivate) {
|
if (this.#autoActivate && !wasActive) {
|
||||||
this._internal_activate();
|
this._internal_activate();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override hostDisconnected(): void {
|
override hostDisconnected(): void {
|
||||||
const wasAttached = this.#attached;
|
const wasAttached = this.#attached;
|
||||||
const wasActive = this.#active;
|
const wasActive = this.isActive;
|
||||||
this.#attached = false;
|
this.#attached = false;
|
||||||
this.#active = false;
|
this.#active.setValue(false);
|
||||||
super.hostDisconnected();
|
super.hostDisconnected();
|
||||||
if (wasAttached === true && wasActive) {
|
if (wasAttached === true && wasActive) {
|
||||||
// CHeck that we have a providerController, otherwise this is not provided. [NL]
|
// Check that we have a providerController, otherwise this is not provided. [NL]
|
||||||
this.#propagateActivation();
|
this.#propagateActivation();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -155,6 +167,18 @@ export class UmbViewController extends UmbControllerBase {
|
|||||||
this.#consumeParentCtrl?.destroy();
|
this.#consumeParentCtrl?.destroy();
|
||||||
this.#consumeParentCtrl = undefined;
|
this.#consumeParentCtrl = undefined;
|
||||||
this.#parentView = context;
|
this.#parentView = context;
|
||||||
|
// Notice because we cannot break the inheritance, we do not need to stop this observation in any of the logic. [NL]
|
||||||
|
this.observe(
|
||||||
|
this.#parentView?.active,
|
||||||
|
(isActive) => {
|
||||||
|
if (isActive) {
|
||||||
|
this._internal_activate();
|
||||||
|
} else {
|
||||||
|
this._internal_deactivate();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
ObserveParentActiveCtrlAlias,
|
||||||
|
);
|
||||||
this.#inheritFromParent();
|
this.#inheritFromParent();
|
||||||
this.#propagateActivation();
|
this.#propagateActivation();
|
||||||
}
|
}
|
||||||
@@ -172,7 +196,7 @@ export class UmbViewController extends UmbControllerBase {
|
|||||||
() => {
|
() => {
|
||||||
this.#computeTitle();
|
this.#computeTitle();
|
||||||
// Check for parent view as it is undefined in a disassembling state and we do not want to update the title in that situation. [NL]
|
// Check for parent view as it is undefined in a disassembling state and we do not want to update the title in that situation. [NL]
|
||||||
if (this.#providerCtrl && this.#parentView && this.#active) {
|
if (this.#providerCtrl && this.#parentView && this.isActive) {
|
||||||
this.#updateTitle();
|
this.#updateTitle();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -184,13 +208,13 @@ export class UmbViewController extends UmbControllerBase {
|
|||||||
#propagateActivation() {
|
#propagateActivation() {
|
||||||
if (!this.#parentView) return;
|
if (!this.#parentView) return;
|
||||||
if (this.#inherit) {
|
if (this.#inherit) {
|
||||||
if (this.#active) {
|
if (this.isActive) {
|
||||||
this.#parentView._internal_childActivated();
|
this.#parentView._internal_childActivated();
|
||||||
} else {
|
} else {
|
||||||
this.#parentView._internal_childDeactivated();
|
this.#parentView._internal_childDeactivated();
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (this.#active) {
|
if (this.isActive) {
|
||||||
this.#parentView._internal_deactivate();
|
this.#parentView._internal_deactivate();
|
||||||
} else {
|
} else {
|
||||||
this.#parentView._internal_activate();
|
this.#parentView._internal_activate();
|
||||||
@@ -209,7 +233,7 @@ export class UmbViewController extends UmbControllerBase {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
this.#autoActivate = true;
|
this.#autoActivate = true;
|
||||||
if (this.#active === true) {
|
if (this.isActive) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// If not attached then propagate the activation to the parent. [NL]
|
// If not attached then propagate the activation to the parent. [NL]
|
||||||
@@ -219,7 +243,7 @@ export class UmbViewController extends UmbControllerBase {
|
|||||||
}
|
}
|
||||||
this.#propagateActivation();
|
this.#propagateActivation();
|
||||||
} else {
|
} else {
|
||||||
this.#active = true;
|
this.#active.setValue(true);
|
||||||
this.#propagateActivation();
|
this.#propagateActivation();
|
||||||
this.#updateTitle();
|
this.#updateTitle();
|
||||||
// TODO: Start shortcuts. [NL]
|
// TODO: Start shortcuts. [NL]
|
||||||
@@ -266,8 +290,8 @@ export class UmbViewController extends UmbControllerBase {
|
|||||||
// eslint-disable-next-line @typescript-eslint/naming-convention
|
// eslint-disable-next-line @typescript-eslint/naming-convention
|
||||||
public _internal_deactivate() {
|
public _internal_deactivate() {
|
||||||
this.#autoActivate = false;
|
this.#autoActivate = false;
|
||||||
if (!this.#active) return;
|
if (!this.isActive) return;
|
||||||
this.#active = false;
|
this.#active.setValue(false);
|
||||||
// TODO: Stop shortcuts. [NL]
|
// TODO: Stop shortcuts. [NL]
|
||||||
// Deactivate parents:
|
// Deactivate parents:
|
||||||
this.#propagateActivation();
|
this.#propagateActivation();
|
||||||
@@ -298,7 +322,7 @@ export class UmbViewController extends UmbControllerBase {
|
|||||||
|
|
||||||
override destroy(): void {
|
override destroy(): void {
|
||||||
this.#inherit = false;
|
this.#inherit = false;
|
||||||
this.#active = false;
|
this.#active.setValue(false);
|
||||||
this.#autoActivate = false;
|
this.#autoActivate = false;
|
||||||
(this as any).provideAt = undefined;
|
(this as any).provideAt = undefined;
|
||||||
this.unprovide();
|
this.unprovide();
|
||||||
|
|||||||
Reference in New Issue
Block a user