无法从另一个组件强制在 agular2 中渲染
Cannot force render in agular2 from another component
我有以下情况:
组件@permissions
这个组件有一个按钮,可以触发一个简单的承诺,并在我的另一个组件@MenuComponent
上设置一个值
export class Permissions {
constructor(private _menu: MenuComponent, private _api: ApiService) {}
btnAction(){
this._api.getDataID(item.project_name, 'usersbyID', userID).then((data: any) => {
this._menu.checkPerm(JSON.parse(data.permissions).description);
});
}
}
返回什么并不重要,但它很简单 JSON。
在我的另一个组件@MenuComponent
@Component({
// ..another configuration non relevant
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class MenuComponent implements OnInit {
menus = []
menuPermisson: any;
menuObservable = new Subject();
constructor(private _cdRef: ChangeDetectorRef) {
this.menuObservable.subscribe(value => {
this.menuPermisson = value;
this.reloadAll();
});
}
reloadAll() {
this.menus.push('someValue');
this._cdRef.markForCheck();
}
checkPerm(data) {
this.menuObservable.next(data);
}
}
所以概念是在 promise 向我的主题发送一些值之后我需要将 someValue 推送到菜单直到此时所有数据都可以到达那里,但是我需要重新呈现视图所以 "someValue" 显示在视图上。但是当我将 this._cdRef.markForCheck()
更改为 this._cdRef.detectChanges()
并将其放在 tryCatch 上时,它什么也没做 returns Attempt to use a destroyed view: detectChanges
。我找不到用 someValue 呈现菜单的方法。
这两个组件在 ChangeDetection 树上处于同一级别
尝试ApplicationRef.tick()
。这是 "always working" 解决方法。
import { ApplicationRef } from '@angular/core';
export SomeComponent {
constructor(private appRef: ApplicationRef) {}
public thisShouldCauseChangeDetection(): void {
this.appRef.tick();
}
}
这里问了类似的问题:
有关 ApplicationRef 的更多信息:https://angular.io/api/core/ApplicationRef
您的问题的最佳解决方案是使用 Component <-> Service <-> Component
通信:
https://angular.io/guide/component-interaction#parent-and-children-communicate-via-a-service
不要将值推入 this.menus
尝试这样的事情
reloadAll() {
var tmp = this.menus.slice();
tmp.push('some valuue');
this.menus=tmp;
}
我对这个案例的解决方案是 Maciej Treder 的建议,
他说:
'The best solution for your problem would be to use Component <-> Service <-> Component
communication: https://angular.io/guide/component-interaction#parent-and-children-communicate-via-a-service'
所以我创建了一个服务来监听 @PermissionModule
所做的更改,并向 @MenuComponent
发送一个更改事件,从中我能够将值推送到 menus
数组并渲染视图,没有 .tick()
或 .detectChanges()
服务组件
@Injectable()
export class SharedServiceMenu {
// Observable string sources
private emitChangeSource = new Subject<any>();
// Observable string streams
changeEmitted$ = this.emitChangeSource.asObservable();
// Service message commands
emitChange(change: any) {
this.emitChangeSource.next(change);
}
constructor() { }
}
我想在哪里发出事件:
// ...irrelevant code
constructor(private: _shared: SharedServiceMenu){}
this._shared.emitChange(data);
以及我想听的变化 emmited
// ... IrrelevantCode
constructor(private _shared: SharedServicesMenu){}
this._shared.changeEmitted$.subscribe((data) => {
//Do what ever you want with data emmited here
}, (err) => {
console.log(err);
}, () => {
console.log('Complete!');
});
我有以下情况:
组件@permissions 这个组件有一个按钮,可以触发一个简单的承诺,并在我的另一个组件@MenuComponent
上设置一个值export class Permissions {
constructor(private _menu: MenuComponent, private _api: ApiService) {}
btnAction(){
this._api.getDataID(item.project_name, 'usersbyID', userID).then((data: any) => {
this._menu.checkPerm(JSON.parse(data.permissions).description);
});
}
}
返回什么并不重要,但它很简单 JSON。
在我的另一个组件@MenuComponent
@Component({
// ..another configuration non relevant
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class MenuComponent implements OnInit {
menus = []
menuPermisson: any;
menuObservable = new Subject();
constructor(private _cdRef: ChangeDetectorRef) {
this.menuObservable.subscribe(value => {
this.menuPermisson = value;
this.reloadAll();
});
}
reloadAll() {
this.menus.push('someValue');
this._cdRef.markForCheck();
}
checkPerm(data) {
this.menuObservable.next(data);
}
}
所以概念是在 promise 向我的主题发送一些值之后我需要将 someValue 推送到菜单直到此时所有数据都可以到达那里,但是我需要重新呈现视图所以 "someValue" 显示在视图上。但是当我将 this._cdRef.markForCheck()
更改为 this._cdRef.detectChanges()
并将其放在 tryCatch 上时,它什么也没做 returns Attempt to use a destroyed view: detectChanges
。我找不到用 someValue 呈现菜单的方法。
这两个组件在 ChangeDetection 树上处于同一级别
尝试ApplicationRef.tick()
。这是 "always working" 解决方法。
import { ApplicationRef } from '@angular/core';
export SomeComponent {
constructor(private appRef: ApplicationRef) {}
public thisShouldCauseChangeDetection(): void {
this.appRef.tick();
}
}
这里问了类似的问题:
有关 ApplicationRef 的更多信息:https://angular.io/api/core/ApplicationRef
您的问题的最佳解决方案是使用 Component <-> Service <-> Component
通信:
https://angular.io/guide/component-interaction#parent-and-children-communicate-via-a-service
不要将值推入 this.menus
尝试这样的事情
reloadAll() {
var tmp = this.menus.slice();
tmp.push('some valuue');
this.menus=tmp;
}
我对这个案例的解决方案是 Maciej Treder 的建议, 他说:
'The best solution for your problem would be to use Component <-> Service <-> Component
communication: https://angular.io/guide/component-interaction#parent-and-children-communicate-via-a-service'
所以我创建了一个服务来监听 @PermissionModule
所做的更改,并向 @MenuComponent
发送一个更改事件,从中我能够将值推送到 menus
数组并渲染视图,没有 .tick()
或 .detectChanges()
服务组件
@Injectable()
export class SharedServiceMenu {
// Observable string sources
private emitChangeSource = new Subject<any>();
// Observable string streams
changeEmitted$ = this.emitChangeSource.asObservable();
// Service message commands
emitChange(change: any) {
this.emitChangeSource.next(change);
}
constructor() { }
}
我想在哪里发出事件:
// ...irrelevant code
constructor(private: _shared: SharedServiceMenu){}
this._shared.emitChange(data);
以及我想听的变化 emmited
// ... IrrelevantCode
constructor(private _shared: SharedServicesMenu){}
this._shared.changeEmitted$.subscribe((data) => {
//Do what ever you want with data emmited here
}, (err) => {
console.log(err);
}, () => {
console.log('Complete!');
});