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

Я пытаюсь сделать двустороннюю привязку, которая кажется простой, но я не могу понять это.

У меня есть список выбора, который содержит все типы контактов, это отображается на Страница сведений о контакте.

Некоторым контактам не будет назначен тип контакта. Если тип контакта не назначен, я разработал веб-API для возврата значения null для contact.contactType.

. При попытке связать список и contact.contactType равен null, я получаю ошибка 'Cannot read property 'id' of null', что имеет смысл. Это ломает страницу.

Если возможно, я бы хотел, чтобы API возвращал значение null. Если ничего не назначено, я сохраняю null в базе данных для столбца [Contact]. [ContactTypeId].

Является ли структура API и базы данных неверной и должна быть разработана по-другому? Я хотел бы думать нет. Это просто таблица [Contact] со столбцом [ContactTypeId] и таблица [ContactType] со столбцом [Id]. Запрос SQL для получения записи контакта присоединяется к [ContactType]. [Id] в [Contact]. [ContactTypeId]. Похоже, это должно работать просто отлично.

Разве я не должен возвращать null значение для contact.contactType?

Как мне go справиться с этой ситуацией?


Я пытался использовать [(ngModel)]="contact.contactType?.id">, но получаю ошибку 'The '?.' operator cannot be used in the assignment'.


Ответ API: Контакт с типом контакта

{
    "id": 1,
    "name": "John Doe",
    "contactType": {
        "id": 1,
        "name": "General Contractor",
        "description": "Some description"
    }
}

Ответ API: Контакт без типа контакта

{
    "id": 1,
    "name": "John Doe",
    "contactType": null
}

Ответ API: Список типов контактов

[
    {
        "description": "Aquatic Consultant description",
        "id": 1,
        "name": "Aquatic Consultant"
    },
    {
        "description": "Architect description",
        "id": 2,
        "name": "Architect"
    },
    {
        "description": "Facility description",
        "id": 3,
        "name": "Facility"
    },
    {
        "description": "General Contractor description",
        "id": 4,
        "name": "General Contractor"
    },
    // ... more contact types ...
]

contact-details.component.ts

@Component({
  selector: 'app-contact-details',
  templateUrl: './contact-details.component.html',
  styleUrls: ['./contact-details.component.scss']
})
export class ContactDetailsComponent implements OnInit {

  contact: Contact;
  contactTypes: ContactType[];

  constructor(
    private _apiService: ApiService,
    private _route: ActivatedRoute,
    private _toastr: ToastrService) { }

  ngOnInit() {
    this.getContact();
    this.getContactTypes();
  }

  private getContact(): void {
    const id = +this._route.snapshot.paramMap.get('id');
    this._apiService.contacts.findById(id)
      .subscribe(
        contact => { this.contact = contact; },
        error => {
          switch (error.status) {
            case 404:
              this._toastr.error('Contact not found');
              break;
            default:
              this._toastr.error(error);
              break;
          }
        });
  }

  private getContactTypes(): void {
    this._apiService.contacts.getContactTypes()
      .subscribe(
        types => this.contactTypes = types,
        error => this._toastr.error(error));
  }

contact-details.component . html

<mat-form-field class="w-100">
    <mat-label>Type</mat-label>
    <mat-select [(ngModel)]="contact.contactType.id"> <!-- Here is the error -->
        <mat-option [value]="null">None</mat-option>
        <mat-option *ngFor="let contactType of contactTypes" [value]="contactType.id">
            {{ contactType.name }}
        </mat-option>
    </mat-select>
</mat-form-field>

contact.model.ts

import { ContactType } from './contact-type.model';

export class Contact {
    constructor() { }

    public id: number;
    public name: string;
    public contactType: ContactType;
}

contact-type.model.ts

export class ContactType {
    constructor() { }

    public id: number;
    public description: string;
    public name: string;
}

Ответы [ 2 ]

0 голосов
/ 19 марта 2020

Я нашел временное решение для этого. При загрузке страницы с контактом, у которого нет типа контакта, список выбора связывается правильно и выбирает значение по умолчанию. Сохранение контакта без назначенного типа контакта все еще сохраняет null в таблице базы данных.

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

Так что, если у вас есть лучшее решение, пожалуйста, не стесняйтесь писать.

I изменил обратный вызов getContact () для создания пустого ContactType, если API возвращает null для contact.contactType.


this._apiService.contacts.findById(id)
    .subscribe(
        contact => { 
            this.contact = contact; 
            if (!this.contact.contactType) {
                this.contact.contactType = new ContactType();
            }
        },
        error => {
            ... omitted ...
        }
    });
0 голосов
/ 19 марта 2020

Я бы попробовал иметь пустой объект перед вашим вызовом API. Ваша ошибка может быть вызвана задержкой заполнения вашей переменной

в вашей contact-details.component.ts операции, подобной

contact: Contact = {
    id: -1,
    name: "";
    contactType: {
        id: -1,
        description: '',
        name: ''
    }
}

, это позволит браузеру не пытаться получить доступ к атрибуту из null

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...