Как объявить переменную зависит от другой в Angular 8 - PullRequest
1 голос
/ 13 марта 2020

Обновлена ​​ссылка на стек: https://stackblitz.com/github/Cheong-LiJie/student-program

Я новичок в Angular 8 и кодирую проект колледжа, в котором пользователь может зарегистрировать ученика и профессора.

У меня есть 2 интерфейса: «Студент» и «Профессор», и каждый профессор занимается разными предметами, и если студент изучает предмет «ИТ», то его профессором будет «А», если он учитывает, то его профессором будет «Б».

Единственный способ, которым я могу думать, - это создать выражение if..else, подобное

if (student.subject == IT){
   student.professor == Dr. Kenny
}else {
   student.professor == Dr. John
}

Но это просто жесткий код, и каждый раз, когда я добавляю нового профессора и предмет, мне нужно измените код снова. Как я могу объявить, что student.prof Professor зависит от Professor.subject и student.subject?

College.ts:

export interface IStudent{
  id:number;
  name:string;
  age:number;
  subject:string;
  education:string;
  professor:string;
}

export interface IProfessor{
  id:number;
  name:string;
  faculty:string;
  subject:string;
}

in-memory-data.service.ts

export class InMemoryDataService implements InMemoryDbService{

  createDb() {
    var students = [
  {"id":1,"name":"John","age":22,"subject":"IT","education":"Diploma"},
  {"id":2,"name":"Austine","age":26,"subject":"Business","education":"Degree"},
  {"id":3,"name":"Samantha","age":24,"subject":"Account","education":"Diploma"},
  {"id":4,"name":"Lily","age":25,"subject":"IT","education":"Degree"},
  {"id":5,"name":"Ken","age":19,"subject":"Account","education":"Diploma"},
    ];

    var professors = [
      {  "id":1, "name":"Dr. Lim","faculty":"FOCS","subject":"IT"},
      {  "id":2, "name":"Professor Anthony","faculty":"FASC","subject":"Account"},
      {  "id":3, "name":"Ms. Pua","faculty":"FAFB","subject":"Business"}
    ];
    return {students,professors};
  }

studentList. html

<table class="table table-dark table-hover table-striped table-bordered">
  <thead class="thead-dark">
    <tr>
      <th>ID</th>
      <th>Name</th>
      <th>Age</th>
      <th>Programme</th>
      <th>Education</th>
      <th>Professor</th>
      <th>Action</th>
    </tr>
  </thead>
  <tbody id="myTable">
    <tr *ngFor="let student of students">
      <a routerLink="/student-detail/{{ student.id }}">
        <td>{{ student.id }}</td>
      </a>
      <td>{{ student.name }}</td>
      <td>{{ student.age }}</td>
      <td>{{ student.subject }}</td>
      <td>{{ student.education }}</td>
      <td>{{ student.professor }}</td>
    <td>

student.component.ts

export class StudentListComponent implements OnInit {
  students: IStudent[];
  public successMsg: string;
  public popoverTitle : string = 'Confirmation Dialog';
  public popoverMessage : string = 'Are you sure you want to delete this student?';
  public confirmClicked : boolean = false;
  public cancelClicked : boolean = false;

  @ViewChild(StudentDetailComponent) child;

  constructor(
    private _studentService: StudentService,
    private route: ActivatedRoute,
    private router: Router,
  ) {}

  ngOnInit() {
    this._studentService
      .getStudents()
      .subscribe(data => (this.students = data));

    this.successMsg = this.child.successMsg;
  }


  delete(student: IStudent): void {
    this.students = this.students.filter(s => s !== student);
    this._studentService
      .delete(student)
      .subscribe(
        data =>
          (this.successMsg = "You have deleted student with ID " + student.id)
      );
  }

  private loadAllUsers() {
    this._studentService.getStudents().subscribe(students => {
      this.students = students;
    });
  }
}

student.service.ts:

export class StudentService {
  private _url = "api/students";

  constructor(
    private _http: HttpClient,
    private messageService: MessageService
  ) {}

  delete(student: IStudent | number): Observable<IStudent> {
    const id = typeof student === "number" ? student : student.id;
    const url = `${this._url}/${id}`;

    return this._http.delete<IStudent>(url);
  }

  private log(message: string) {
    this.messageService.add(`StudentService: ${message}`);
  }

  getStudents(): Observable<IStudent[]> {
    return this._http.get<IStudent[]>(this._url);
  }

  getStudent(id: number): Observable<IStudent> {
    const url = `${this._url}/${id}`;
    return this._http.get<IStudent>(url);
  }

  addStudent(student: IStudent): Observable<any> {
    return this._http.post<any>(this._url, student);
  }
  updateStudent(student: IStudent): Observable<any> {
    return this._http.put<any>(this._url, student);
  }
}

Ответы [ 3 ]

4 голосов
/ 13 марта 2020

Как я могу объявить, что student.prof преподаватель зависит от Professor.subject и student.subject?

Вы настроили свои интерфейсы так называемым денормализованным способом. Под этим я подразумеваю, что вы храните информацию об уникальной сущности в нескольких сущностях.

В вашем домене есть как минимум следующие понятия сущности:

  • student
  • профессор
  • предмет

Субъект и ученик (в зависимости от обстоятельств) имеют отношения один ко многим. Один предмет может иметь много студентов. Один студент может иметь один предмет.

Субъект и профессор имеют отношения один-к-одному. Один предмет может иметь одного профессора. У одного профессора может быть один предмет (я полагаю).

Проект

У субъекта есть одно свойство - его имя. У профессоров много свойств. Вы можете сохранить предмет на профессоре, а предмет профессора на ученике.

export interface IStudent{
  id:number;
  name:string;
  age:number;
  education:string;
  professor: IProfessor;
}

export interface IProfessor{
  id:number;
  name:string;
  faculty:string;
  subject:string;
}

Затем вы получите предмет студента через профессора:

const subject = student.professor.subject;

Рассматривая предмет как объект

Кроме того, вы можете рассматривать объект как объект. Также обычно сохраняют идентификатор сложного объекта и затем ищут его, когда вам это нужно.

export interface IStudent{
  id:number;
  name:string;
  age:number;
  education:string;
  subjectId: number;
}

export interface IProfessor{
  id:number;
  name:string;
  faculty:string;
}

export interface ISubject{
  id: number;
  name: string;
  professorId: number;
}

Вы должны добавить уникальные сущности для каждой сущности (в пределах каждого массива сущностей), а затем искать сущности, когда вам это нужно.

Например:

const student = this.service.getStudent(1);
const subject = this.service.getSubject(student.subjectId);
const professor = this.service.getProfessor(subject.professorId);

Где методы обслуживания - это какой-то оптимизированный способ поиска сущности по ее идентификатору.

Как выбрать дизайн?

При выборе дизайна никогда не бывает одного выбора. Какой из них вы выберете, зависит от того, как он лучше всего соответствует вашим потребностям. Это касается не только дизайна сущностей, но и того, как вы его храните. Если у вас 1000 учеников и много запросов, вам не нужно каждый раз искать по всему массиву, просто чтобы найти ученика по его идентификатору.

1 голос
/ 13 марта 2020

Я думаю, что идея заключается в том, чтобы "кэшировать" профессоров (профессорами будут несколько профессоров)

profesor.service

professors:IProfessor[]=null;
 getProfessors(): Observable<IProfessor[]> {
    return this.professors? of(this.professors):
      this._http.get<IProfessor[]>(this._url).pipe(
         tap(res=>{
            this.professors=res;
         })
      ); 
  }

Затем в файле student.service вы можете изменить getStudents и getStudent, чтобы получить профессора

getStudents(): Observable<IStudent[]> {
    return forkJoin(this._professorService.getProfessors(),this._http.get<IStudent[]>(this._url)).pipe(
    map(([professors,students]:[IProfessor[],IStudent[]])=>{
       students.forEach(x=>{
          const professor=professors.find(p=>p.subject==x.subject)
          x.professor=professor 
          //you can also only get the name, e.g.
          //x.profesorName=profesor?profesor.name:''
       })
       return students
    })
  )
  }

getStudent(id: number): Observable<IStudent> {
    const url = `${this._url}/${id}`;
    return forkJoin(this._professorService.getProfessors(),
                    this._http.get<IStudent>(url)).pipe(
    map(([professors,student]:[IProfessor[],IStudent])=>{
          const professor=professors.find(p=>p.subject==student.subject)
          student.professor=professor 
          //you can also only get the name, e.g.
          //student.profesorName=profesor?profesor.name:''
         return student
    })
    )
  }
0 голосов
/ 13 марта 2020

Вместо использования оператора if вы можете выполнить поиск по теме в массиве профессоров. Что-то вроде этого назначит первый профессор предмета,

const professor = professors.find(p => p.subject === student.subject);
student.professor = professor ? professor.name : null;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...