Как мне установить значение для моей модели, используя элемент управления select, если связанная модель отличается от моей опции select? - PullRequest
0 голосов
/ 07 января 2019

Я давно использую AngularJS и недавно углубляюсь в новые Angular и .NET Core. С моим новым усилием я начал изучать огромные изменения в Entity Framework Core. Одно из самых значительных изменений касается отношений «многие ко многим». Ранее у вас была возможность скрыть соединительную таблицу, которая хорошо выровнялась с AngularJS, потому что свойство навигации в ngModel могло быть того же типа, что и значение параметра. Теперь, когда это больше не вещь, мы должны найти способ преобразования из одной сущности в другую. Вот мои модели:

Transaction.cs

public class Transaction
{
    public int Id { get; set; }

    public DateTime Date { get; set; }

    public string AccountNumber { get; set; }

    public string Key { get; set; }

    public decimal Amount { get; set; }

    public string Description { get; set; }


    public virtual IList<CategoryTransaction> CategoryTransactions { get; set; }
}

Category.cs

public class Category
{
    public int Id { get; set; }

    public string Name { get; set; }


    public virtual IList<CategoryTransaction> CategoryTransactions { get; set; }
}

CategoryTransaction.cs

public class CategoryTransaction
{
    public int CategoryId { get; set; }

    public int TransactionId { get; set; }


    public virtual Category Category { get; set; }

    public virtual Transaction Transaction { get; set; }
}

Я использую TypeScript и определил свои модели, и моя форма разметки выглядит следующим образом:

<form>
  <mat-form-field>
    <mat-select [compareWith]="compareFn" placeholder="Categories" [(ngModel)]="testTransaction.categoryTransactions" multiple name="foo">
      <mat-option *ngFor="let category of categoryList" [value]="category">{{ category.name }}</mat-option>
    </mat-select>
  </mat-form-field>
</form>

и вот мое сравнениеFn:

compareFn(category: Category, categoryTransaction: CategoryTransaction) {
    return categoryTransaction && category ? categoryTransaction.categoryId === category.id : false;
}

Я пришел сюда и начал думать: «Как я собираюсь конвертировать из Category в CategoryTransaction? Я искал способы сортировки« подключиться »к событию установщика модели и создать объект CategoryTransaction, используя выбранный Category, но я не смог найти способ подключения. Затем я увидел в сообщении, что вы можете использовать JSON в атрибуте значения. Поэтому я изменил свою разметку и сравнил функцию с этой:

<form>
  <mat-form-field>
    <mat-select [compareWith]="compareFn2" placeholder="Categories" [(ngModel)]="testTransaction.categoryTransactions" multiple name="foo">
      <mat-option *ngFor="let category of categoryList" [value]="{ categoryId: category.id, transactionId: 1 }">{{ category.name }}</mat-option>
    </mat-select>
  </mat-form-field>
</form>

и

compareFn2(c1: CategoryTransaction, c2: CategoryTransaction) {
    return c1 && c2 ? c1.categoryId === c2.categoryId : false;
}

Это работает, но мне это не нравится. Это кажется грязным / хакерским и, кажется, не вписывается в «Угловой путь», где мы работаем с объектами. Я не думаю, что представление должно быть там, где мы конвертируем значения. Я предполагал, что буду «обновлять» CategoryTransaction и устанавливать значение или реализовывать какой-либо преобразователь значений. Поскольку я буду конвертировать / устанавливать значение в TypeScript, если моя модель изменится, компилятор TypeScript, надеюсь, будет жаловаться, если я его пропущу.

Так что это похоже на общий сценарий (многие-ко-многим), когда люди сталкивались с EF Core + Angular, но у меня возникают проблемы с поиском хорошего примера. Кто-нибудь нашел хороший способ справиться с этим сценарием или, может быть, есть хороший пример для переопределения значения ngModel с помощью элемента управления select?

Я использую .NET Core 2.1, Angular 7.0.4, Material 7.0.4 и EF Core Sql Server 2.1.4.

1 Ответ

0 голосов
/ 08 января 2019

Используя <mat-select> Я решил подписаться на событие selectionChange и посмотреть, что оно мне предоставит.

<form>
  <mat-form-field>
    <mat-select [compareWith]="compareFn" placeholder="Categories" [(ngModel)]="testTransaction.categoryTransactions" multiple name="foo" (selectionChange)="categoryChange($event, testTransaction)">
      <mat-option *ngFor="let category of categoryList" [value]="category">{{ category.name }}</mat-option>
    </mat-select>
  </mat-form-field>
</form>

Я передал ему аргумент $event и объект Transaction.

// Respond to when the selection changes
categoryChange(event: MatSelectChange, transaction: Transaction) {
    // Rather than trying to manually detect what changed, just clear out all the options
    transaction.categoryTransactions = [];
    // Iterate through all the selected options
    for (var i: number = 0; i < event.value.length; i++) {
      // Add a new CategoryTransaction for each selected Category
      transaction.categoryTransactions.push({
        transactionId: transaction.id,
        categoryId: event.value[i].id
      });
    }
}

Параметр объекта $event передает все выбранные объекты Category, а параметр Transaction - это объект, который содержит все записи таблицы объединения. Я боялся, что, изменив transaction.categoryTransactions, который связан с ngModel, я могу застрять в бесконечном цикле стрельбы события selectionChange, но, к моему облегчению, это оказалось не так.

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