Angular ExpressionChangedAfterItHasBeenCheckedError со встроенной таблицей редактирования

avatar
rgoal
29 мая 2018 в 19:02
598
2
0

У меня есть таблица, в которой вызывается дочерний компонент с именем модальный, модальный компонент имеет две кнопки сохранения и отмены, которые используются для встроенного редактирования. Я знаю, что мне нужно использовать «ChangeDetectorRef», но я не могу понять, как использовать событие «ngAfterViewInit» с моим кодом

ExpressionChangedAfterItHasBeenCheckedError: Выражение изменилось после того, как его проверили. Предыдущее значение: «disableEditSaveButton: false». Текущее значение: 'disableEditSaveButton: true'.

dashboard.HTML

 <p-table #dt  [value]="iToDoList" dataKey="id"  [paginator]="true" [rowsPerPageOptions]="[10,50,100]"
                             [rows]="10">

                        <ng-template pTemplate="header">
                            <tr>
                                <th>ID</th>
                                <th>Comment</th>
                                <th>Action</th>

                            </tr>
                            </ng-template>
                            <ng-template pTemplate="body" let-row>  
                                <tr>
                                    <td>{{row.id}}</td>
                                    <td>
                                        <div  *ngIf="!row.isEditable">{{row.comment}}</div>
                                        <div *ngIf="row.isEditable">
                                            <input type="text" [(ngModel)]="row.comment">
                                            <span *ngIf="isEmpty(row.comment)" style="color:crimson">Required</span>
                                        </div>
                                    </td>
                                    <td>
                                        <div>
                                            <modal  [disableEditSaveButton]='disableSaveButton' (open)="onOpen(row)" [showModal]="!row.isEditable"  (selectedRow)="onSelectedRow(row)" (cancelEdit)="onCancelEdit(row)"></modal>
                                        </div>
                                        <!--<button (click)="editRow(row)">Edit</button>-->
                                    </td>
                                    <td>                                <button (click)="save(row)">Save</button></td>
                                </tr>
                            </ng-template>

                    </p-table>

dashboard.compnent (это вызывает ExpressionChangedAfterItHasBeenCheckedError)

 isEmpty(input) {
        if (input.replace(/\s/g, '') === "") {

            this.disableSaveButton = true;
        }
        else {
            this.disableSaveButton = false;
       }
       // this.cdr.detectChanges();

        return input.replace(/\s/g, '') === "";
    }

modal.html

   <div *ngIf='!showModal'>
        <button type="button" class="btn-xs btn-primary" (click)="onSave()" [disabled]='disableEditSaveButton'>Save</button>
        <button type="button" class="btn-xs btn-orange" (click)="onCancelEdit()">Cancel</button>
    </div>

modal.component

@Input() disableEditSaveButton: boolean = false;

******************ОБНОВЛЕНИЕ******************************* ************************************************

браузер все еще выдает ExpressionChangedAfterItHasBeenCheckedError

Компонент

   isEmpty(input) {

        this.cdr.detach();

        if (input.replace(/\s/g, '') === "") {

            this.disableSaveButton = true;
        }
        else {
            this.disableSaveButton = false;
        }
        // this.cdr.detectChanges();

        // restart change detection for this view
        this.cdr.reattach();

        return input.replace(/\s/g, '') === "";
    }
Источник
Vikas
29 мая 2018 в 19:14
0

blog.angularindepth.com/…

rgoal
29 мая 2018 в 20:04
0

Я видел эту статью и попытался сделать ngAfterViewInit() { this.cdr.detectChanges(); } это все еще не работает, потому что я устанавливаю дочерний ввод не в ngAfterViewInit. Не уверен, как бы я это сделал, если дочерние значения должны быть установлены в методе «isEmpty»

rgoal
30 мая 2018 в 00:11
0

Я использовал setTimeout, он работал, но очень медленно... Мне нужно лучшее решение

Ответы (2)

avatar
user6749601
30 мая 2018 в 19:25
1

Хорошо, а теперь еще один подход.

Проанализировав ваш код, я увидел, что

this.disableSaveButton === isEmpty(row.comment)

Это означает, что если isEmpty(row.comment) верно, this.disableSaveButton тоже верно, и наоборот.

Так почему бы вам не использовать результат isEmpty(row.comment) напрямую, а не сохранять его в this.disableSaveButton? При этом у вас не будет изменяющегося выражения, так как первое истинное или ложное также будет последним.

Пожалуйста, попробуйте так:

<modal  [disableEditSaveButton]='isEmpty(row.comment)' 
        (open)="onOpen(row)" 
        [showModal]="!row.isEditable"  
        (selectedRow)="onSelectedRow(row)" 
        (cancelEdit)="onCancelEdit(row)">
</modal>

И если вам не нужен this.disableSaveButton для других целей, кроме вашего модального диалога, что означает, что он вам вообще не нужен сейчас, вы можете уменьшить размер своего метода до этого, не изменяя его логического результата.

isEmpty(input) {
    return input.replace(/\s/g, '') === "";
}
user6749601
30 мая 2018 в 19:27
0

Думаю, я нашел способ установить логическое значение [disableEditSaveButton] только один раз. Таким образом, вы не должны снова сталкиваться с ExpressionChangedAfterItHasBeenCheckedError.

rgoal
30 мая 2018 в 20:05
0

вау, это сработало .. очень простой, но и умный способ ... большое спасибо .. узнал от вас кое-что ценное :)

avatar
user6749601
30 мая 2018 в 07:35
0

Попробуйте так:

isEmpty(input) {
    // stop change detection for this view
    this.cdr.detach(); 

    if (input.replace(/\s/g, '') === "") {

        this.disableSaveButton = true;
    }
    else {
        this.disableSaveButton = false;
   }
   // this.cdr.detectChanges();

    // restart change detection for this view
    this.cdr.reattach(); 

    return input.replace(/\s/g, '') === "";
}
rgoal
30 мая 2018 в 15:51
0

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