我正在通过createComponent
方法创建动态组件,但我无法让child
组件更新input
从{{1}传递给它的值parent
通过component.instance.prop = somevalue
方法,但是当我更新parent
中的值时,孩子没有更新它的引用。
为父级:
import {
Component,
ViewChild,
ViewContainerRef,
ComponentFactoryResolver,
AfterContentInit
} from '@angular/core';
import { ChildComponent } from '../child/child.component';
@Component({
selector: 'parent-component',
template: `
<div>
<input type="text" (keyup)="name = $event.target.value">
<span>{{ name }}</span>
</div>
<ng-container #container></ng-container>
`,
styles: []
})
export class ParentComponent implements AfterContentInit {
@ViewChild('container', { read: ViewContainerRef}) container: ViewContainerRef;
private _name = 'John Doe';
get name() {
return this._name;
}
set name(name: string) {
this._name = name;
}
constructor(private resolver: ComponentFactoryResolver) { }
ngAfterContentInit() {
let factory = this.resolver.resolveComponentFactory(ChildComponent);
let component = this.container.createComponent(factory);
component.instance.name = this.name;
}
}
ChildComponent:
import {
Component,
OnInit,
Input,
OnChanges,
SimpleChanges
} from '@angular/core';
@Component({
selector: 'child-component',
template: `
<div>
{{ name }}
</div>
`,
styles: []
})
export class ChildComponent implements OnChanges {
_name: string;
get name() {
return this._name;
}
set name(name: string) {
this._name = name;
}
constructor() { }
ngOnChanges(changes: SimpleChanges) {
console.log('onchanges ', changes);
this._name = changes.name.currentValue;
}
}
问题:当child
组件中的值发生变化时,如何通过createComponent()
方法创建动态parent
组件来更新其值?
答案 0 :(得分:2)
您可以在父组件中执行此操作。 stackblitz中的Here示例。
template: `
<div>
<input type="text" (keyup)="onKeyUp($event)">
<span>{{ name }}</span>
</div>
<ng-container #container></ng-container>
`,
childComponent: ChildComponent;
ngAfterContentInit() {
let factory = this.resolver.resolveComponentFactory(ChildComponent);
let component = this.container.createComponent(factory);
this.childComponent = component.instance;
this.childComponent.name = this.name;
}
onKeyUp($event) {
const changes = {
name: new SimpleChange(this.name, $event.target.value, false)
}
this.name = $event.target.value;
this.childComponent.ngOnChanges(changes);
}
答案 1 :(得分:0)
只需通过component.instance.name = this.name
重新分配您姓名的每项更改即可。对于此实现,每个(keyup)
事件都有一个处理函数:
@Component({
selector: 'parent-component',
template: `
<div>
<input type="text" (keyup)="onNameChange($event)">
<span>{{ name }}</span>
</div>
<ng-container #container></ng-container>
`,
styles: []
})
export class ParentComponent implements AfterContentInit {
@ViewChild('container', { read: ViewContainerRef}) container: ViewContainerRef;
private component;
private _name = 'John Doe';
get name() {
return this._name;
}
set name(name: string) {
this._name = name;
}
constructor(private resolver: ComponentFactoryResolver) { }
onNameChange(event) {
this.name = event.target.value;
this.component.instance.name = this.name;
}
ngAfterContentInit() {
let factory = this.resolver.resolveComponentFactory(ChildComponent);
this.component = this.container.createComponent(factory);
this.component.instance.name = this.name;
}
}
&#13;
答案 2 :(得分:-1)
如果您创建一个带有可观察对象的服务,该服务会在每次值更改时发出,并且在动态组件的onInit上预订了该服务上的可观察对象,那么您将从可观察对象获得的数据分配给该对象您的组件属性...我使用了类似的方法,并且似乎可以正常工作。
这是我在其中注入CarouselService的parentComponent:
@Component({
selector: 'app-carousel',
templateUrl: './carousel.component.html',
styleUrls: ['./carousel.component.scss'],
providers: [ CarouselService]
})
export class CarouselComponent implements OnInit, AfterViewInit, AfterContentInit {
@ViewChild('entryForSlides', { read: ViewContainerRef }) entryForSlides: ViewContainerRef;
@Input() carouselSlides: Array<CarouselSlide>;
@Input() hasPersistanceService: boolean;
@Output() noSlidesRemaining: EventEmitter<boolean> = new EventEmitter(false);
removedSlideToggle = false;
carrouselInstance: any;
activeIndex = 0;
carouselSlideFactory: ComponentFactory<CarouselSlideComponent>;
constructor( private _resolver: ComponentFactoryResolver, private _carouselService: CarouselService) {
this.carouselSlideFactory = this._resolver.resolveComponentFactory(CarouselSlideComponent);
}
ngOnInit() { }
ngAfterViewInit(): void {
this.carrouselInstance = new Swiper ('.swiper-container', {
init: false,
// loop: true,
spaceBetween: 30,
// speed: 5000,
pagination: {
el: '.swiper-pagination',
},
// Navigation arrows
navigation: {
nextEl: '.swiper-button-nextSlide',
prevEl: '.swiper-button-previousSlide',
}
});
this.carrouselInstance.on('slideChangeTransitionEnd', () => {
this.activeIndex = this.carrouselInstance.realIndex;
this._carouselService.updateIndex(this.activeIndex);
});
this.carrouselInstance.init();
}
ngAfterContentInit(): void {
this.generateSlides();
}
clickOnCross() {
this._carouselService.updateIndex(this.activeIndex);
this.entryForSlides.clear();
this.carouselSlides.splice(this.carrouselInstance.realIndex, 1);
this.generateSlides();
// Timeout to update carousel with the new DOM slides (little hack while a better solution is found): DO NOT REMOVE
setTimeout(() => {
this.carrouselInstance.update();
}, 1);
if (this.carouselSlides.length <= 0 ) {
this.noSlidesRemaining.emit();
}
}
generateSlides() {
this.carouselSlides.forEach((element, index) => {
const component = this.entryForSlides.createComponent(this.carouselSlideFactory);
component.instance.carouselSlide = element;
component.instance.numberOfIndex = index;
component.instance.activeSlide = this.activeIndex;
});
}
}
然后我动态注入的组件是这样的:
@Component({
selector: 'app-carousel-slide',
templateUrl: './carousel-slide.component.html',
styleUrls: ['./carousel-slide.component.scss']
})
export class CarouselSlideComponent implements OnInit, OnDestroy {
@HostBinding('class.swiper-slide') public mustAddSwiperSlideClass = true;
carouselSlide: CarouselSlide;
numberOfIndex: number;
activeSlide: number;
subActiveSlide: Subscription;
constructor(private _carouselService: CarouselService) { }
ngOnInit() {
this.subActiveSlide = this._carouselService.currentIndex.subscribe(
(data: number) => {
this.activeSlide = data;
}
);
}
ngOnDestroy() {
if (this.subActiveSlide) {
this.subActiveSlide.unsubscribe();
}
}
}
因此,当我从parentComponent执行函数clickOnCross时,我需要通过调用服务上的函数来更新动态注入组件上的Input activeSlide,该服务会更新activeSlide并将值发射给所有动态注入组件。这是CarouselService的代码:
@Injectable({
providedIn: 'root'
})
export class CarouselService {
currentIndex = new Subject<number>();
constructor() { }
updateIndex(newIndex: number) {
this.currentIndex.next(newIndex);
}
}