如何在Angular4中为多个项目显示带有* ngFor的模态窗口

时间:2017-12-19 20:17:57

标签: html angular typescript angular5

我正在尝试一个简单的项目来学习Angular,我目前遇到了一个问题: 我正在为一些假人提供服务,然后显示带有人名的方框。当我点击一个方框时,会出现一个模态弹出窗口并显示有关此人的更多信息 - 目前只是一个简短生物的string

问题是我有一个*ngFor来对persons进行迭代,然后我怀疑发生的是我还为每一个创建了一个模态窗口。然后模态窗口不知道哪个是当前选定的人,所以它只显示了列表中第一个人的生物...

所以问题是如何使每个当前选定的人都能工作;即当我点击id = 3的人时,模态显示同一个人的生物。

我想这需要以编程方式完成,这就是为什么我没有使用像href="#modal" data-toggle="modal"之类的东西将模态窗口绑定到事件。

有更好的想法吗?

以下是我的内容:PersonComponent

@Component({
    selector: 'person',
    templateUrl: './person.component.html'
})
export class PersonComponent implements OnInit {

    people: Person[];

    selectedPerson: Person;

    personBio: string;

    @ViewChild('personModal') private personModal;

    constructor(private router: Router,
                private activatedRoute: ActivatedRoute,
                private stateService: StateService,
                private personService: PersonService) {
    }

    ngOnInit() {
        this.loadAllPeople();
    }

    private loadAllPeople() {

        this.personService.getPeople()
            .subscribe(result => {
                this.people = result;
            }, error => {
                this.console.log(error);
            });
    }

    goToPersonEditComponent(person: Person) {
        this.stateService.person = this.selectedPerson;
        this.router.navigate(['../' + FrontendRoute.EDIT], {relativeTo: this.activatedRoute});
    }


    loadPersonBioModal(person: Person) {
        if (this.personModal) {
            this.selectedPerson = person;
            jQuery(this.personModal.nativeElement).modal('show');
        }

        this.personService.getPersonBio(person.id)
            .subscribe((bio) => this.personBio = bio);
    }

    closeModal() {
        if (this.personModal) {
            jQuery(this.personModal.nativeElement).on('hide.bs.modal', (evt) => {
                this.selectedPerson = null;
            });
        }
    }
}

人物编辑组件:我没有展示整个事情,为了保持简单,但我的想法是我得到了所选人员,并且从id属性我可以编辑它的生物。

@Component({
    selector: 'person-edit',
    templateUrl: './person-edit.component.html'
})

export class PersonEditComponent implements OnInit {

    person: Person;

    constructor(private router: Router,
                private activatedRoute: ActivatedRoute,
                private packService: PackService,
                private orderService: PackOrderService,
                private stateService: StateService,
                private eventBusService: EventBusService,
                private loggingService: LoggingService) {

    }

    ngOnInit() {
        this.person = this.stateService.person;
    }     

}

在组件之间传递东西的简单服务(我想用这种方式而不是@Input):

@Injectable()
export class StateService {

    private _person: Person;

    constructor() {
    }

    get person() {
        return this._person;
    }

    set person(person: Person) {
        this._person = person;
    }

    clear() {
        this._person = null;
    }
}

这是我的模板,我有modal

<div>
    <h2 class="h2">People</h2>
    <div class="item-collection item-collection-3-columns item-collection-tablet item-collection-wide">
        <div class="items">
            <article *ngFor="let person of people"
                     (click)="loadPersonBioModal(person)">
                <div class="content">
                    <div class="headline">
                        <span>{{person.name}}</span>
                        <span data-original-title="Show Person's Bio"></span>
                    </div>
                </div>
            </article>
        </div>
    </div>        
</div>

<div #personModal tabindex="-1" role="dialog" class="modal fade" style="display: none;"
     aria-hidden="true">
    <div role="document" class="modal-dialog modal-lg modal-has-header modal-has-footer">
        <div class="modal-content">{{personBio}}</div>
        <div class="modal-footer">
            <div class="section-btns">
                <button type="button" data-dismiss="modal"
                        (click)="closeModal()">Close
                </button>
                <button type="button" data-dismiss="modal"
                        (click)="goToPersonEditComponent(selectedPerson)">Edit Bio
                </button>
            </div>
        </div>
    </div>
</div>

这是PersonService,它进行http调用:

@Injectable()
export class PersonService {

    constructor(private http: HttpClient, private router: Router) {
    }

    getPeople(): Observable<Person[]> {
        return this.http.get<Person[]>(BackendRoute.PERSON_DATA)
            .catch(error => {
                return Observable.throw(new Error('An unexpected error occurred' + error));
            });
    }

    getPersonBio(): Observable<Person> {
        return this.http.get<Person>(BackendRoute.PERSON_BIO)
            .catch(error => Observable.throw(new Error(error)));
            });
    }
}

1 个答案:

答案 0 :(得分:0)

好的,鉴于您的意见,我认为可能发生的事情是您在getPersonBio()返回个人信息并将其分配给personBio财产之前显示您的模式。

解决此问题的一种简单方法是使用async管道为您异步更新值。试试这个,

你的PersonComponent中的

personBio: Observable<Person>;

loadPersonBioModal(person: Person) {
  if (this.personModal) {
    this.selectedPerson = person;
    // directly assigning the returned observable of Person type and let async pipe do its magic in the template
    this.personBio = this.personService.getPersonBio(person.id);
    jQuery(this.personModal.nativeElement).modal('show');
  }
}

在您的模板中

<div class="modal-content">{{ personBio | async }}</div>

您必须导入CommonModule才能正常工作,如docs所示。此外,除非没有其他支持的方法,否则不建议直接在角度使用jQuery方法。

如果有帮助,请告诉我。