【发布时间】:2017-01-11 16:38:21
【问题描述】:
根据Angular 1.5 documentation 组件应该只控制自己的View 和Data。
除了更改传递给组件的对象的属性,组件应该创建原始数据的内部副本,并在该副本发生更改时使用回调通知父组件。
在这个plunk 中,我创建了一个小演示来说明我的问题。
interface IStudent {
id: number,
name: string;
}
/* SERVICE: StudentService */
public class StudentsService {
static $inject = ['$q'];
constructor(private $q: ng.IQService) {
}
public getStudents() : ng.IPromise<IStudent[]> {
return this.$q.when([
{ id: 1, name: 'Adam' },
{ id: 2, name: 'Ben' }
}]);
}
}
/* COMPONENT: student */
class StudentsComponent implements ng.IComponent {
public template = `<student-list on-selected="$ctrl.onSelected(student)"></student-list>
<edit-student student="$ctrl.student" ng-show="$ctrl.student" on-changed="$ctrl.copyChanged(copy)"></edit-student>`;
public controller = StudentsController;
}
class StudentsController {
private student: IStudent;
protected onSelected(student: IStudent) {
this.student = student;
}
protected copyChanged(copy: IStudent) {
this.student.name = copy.name;
}
}
/* COMPONENT: student-list */
class StudentListComponent implements ng.IComponent {
public template = '<ul><li ng-repeat="student in $ctrl.students"><a ng-click="$ctrl.onClick(student)">{{ student.name }}</a></li></ul>';
public controller = StudentListController;
public bindings : any = {
onSelected: '&'
}
}
class StudentListController {
protected students: IStudent[];
static $inject = ['studentsService'];
constructor(private studentsService: StudentsService) {
}
public $onInit() {
this.studentsService.getStudents().then(data => this.students = data);
}
protected onClick(student: IStudent) {
this.onSelected({ student: student });
}
}
/* COMPONENT: edit-student */
class EditStudentComponent implements ng.IComponent {
public template = `<form class="form">
<div class="input-group">
<label for="#" class="control-label">Original</label>
<input type="text" class="form-control" ng-model="$ctrl.student.name" readonly>
</div>
</form>
<form class="form">
<div class="input-group">
<label for="#" class="control-label">Copy</label>
<input ng-change="$ctrl.changed()" type="text" class="form-control" ng-model="$ctrl.copy.name">
</div>
</form>`;
public controller = EditStudentController;
public bindings :any = {
student: '<',
onChanged: '&'
};
}
class EditStudentController {
protected copy: IStudent;
public $onInit() {
console.log('EditStudentComponent.$onInit', this.student);
}
public $onChange() {
console.log('EditStudentComponent.$onChange', this.student);
this.copy = angular.copy(this.student);
}
protected changed() {
console.log('EditStudentController.changed', this.copy);
this.onChanged({ copy: this.copy });
}
}
/* Bootstrap */
angular
.module('app', [])
.component('students', new StudentsComponent())
.component('studentList', new StudentListComponent())
.component('editStudent', new EditStudentComponent())
.service('studentsService', StudentsService)
;
angular.bootstrap(document, ['app']);
我有一个遍历学生的列表。当用户选择一个学生时,会显示一个文本框,用户可以在其中更改学生的姓名。每当名称更改时,此更改都会传播到更新列表的父组件。
问题是在列表中选择一个学生后,edit-user组件没有初始化,仍然显示组件创建时创建的副本名称(null)。
谁能告诉我如何解决这个问题,以便在单击列表中的学生时,编辑组件会使用所选学生的副本进行初始化?
编辑:更改了 plunk,因为我不小心删除了脚本标签而不是样式标签。
【问题讨论】:
标签: angularjs typescript components