Angular - Как пометить отдельный элемент в шаблоне ngfor для MarkForCheck () - PullRequest
0 голосов
/ 01 июня 2018

Я относительно новичок в Angular, поэтому, пожалуйста, прости мой, может быть, тривиальный вопрос.

Я также много погуглил, нашел много похожих вопросов, но ни один из них не был адресованмоя проблема.

Ситуация

Давайте предположим, что шаблон следующего компонента:

<div class="wrapper">
    <!-- Stuff -->
    .
    .
    .
    <div *ngFor="let group of groups">
        <button #btn (click)="onClick(btn, group)">Change group title</button>
        <div class="group-title">
            {{group.title | translate}}
        </div>
        .    
        .    
        .    
        <div *ngFor="let item of group.subGroup">
            {{item.title}}
            .    
            .    
            .    
        </div>
    </div>
<div/>

Теперь я хочу, чтобы пользователь мог запускать серию действий / событий, которые в конечном итогеизменить заголовок одной группы (один элемент в ngFor).

Т.е.

onClick(btnRef, group) {
    .    
    .    
    .
    anAsyncronousEvent.subscribe(
        success => group.title = success.BrandNewTitle;
    )    
}

Желаемый результат

В DOM должен отображаться новый заголовок затронутой группы,но это не так.Я также пробовал без канала 'translate', но тщетно.

Поискав в поиске, я понимаю, что изменение DOM обнаруживается только Angular * , глядя на ссылка на объект используется для генерации элементов ngFor, поэтому, если я изменяю только какое-то внутреннее свойство объекта / элемента, событие ChangeEvent не запускается.

Возможные решения

OneИдея может заключаться в том, чтобы сделать глубокую копию объекта Group и заменить соответствующий элемент в массиве за ngFor, но это нанесло бы урон всему бесполезному созданию Angular refresh DOM only для того, что действительно изменилось.Другая идея может заключаться в использовании markForCheck (), но здесь у меня есть два варианта:

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

2) Я мог бы каким-то образом создать подкомпонент только для заголовка группы, но мне это кажется излишним, и я также не уверен, что это сработает.

Итак, как заставить Angular обновить ТОЛЬКО название группы?

Заранее всем спасибо

РЕДАКТИРОВАТЬ

ОК.Вероятно, приведенный выше код немного упрощен.

Этот пример ближе к моему реальному приложению и работает на stackblitz здесь , где он воспроизводит проблему, которую я пытаюсь решить..

// Template
<div class="wrapper">
    <div *ngFor="let group of groups">
        <button #btn (click)="onClick(btn, group)">Pop away item</button>
        <div class="group-title">
            Group info: count = {{group.info | format}}
        </div>
        <div *ngFor="let item of group.items">
            &nbsp;&nbsp;&nbsp;&nbsp;Item title: "{{item.title}}"
        </div>
    </div>
</div>

//Component
onClick(btn, group: any) {
  setTimeout(() => { // In the real App this is an Observable
    let i = this.groups.indexOf(group);
    group.items.pop();
    group.info.count--;
  }, 1000);
}

Я ожидаю, что количество отображаемых элементов уменьшится после нажатия кнопки, но это не так.

1 Ответ

0 голосов
/ 01 июня 2018

В соответствии с вашим требованием, если вы не хотите обновлять целые группы [], а хотите изменить только заголовок конкретной группы в DOM, вы можете просто передать индекс группы событию clickи использовать его для динамической генерации идентификаторов, чтобы вы могли получить доступ к этому идентификатору и изменить значение HTML при запуске события.Что-то вроде ниже

<div *ngFor="let group of groups; let i = index">
    <button #btn (click)="onClick(btn, group, i)">Change group title</button>
    <div class="group-title" id="group{{i}}">
        {{group.title | translate}}
    </div>
    .    
    .    
    .    
    <div *ngFor="let item of group.subGroup">
        {{item.title}}
        .    
        .    
        .    
    </div>
</div>

Здесь вы можете использовать этот индекс "i" для обновления ваших групп [], а затем, поскольку у вас есть доступ с уникальным идентификатором, вы можете изменить значение в этом.

onClick(btnRef, group, index) {
.    
.    
.
anAsyncronousEvent.subscribe(
    success => {
         document.getElementById(`group${index}`)
             .text(success.BrandNewTitle);
      }
    )    
  }

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

...