Запуск виявлення змін вручну в кутовій


387

Я пишу Angular компонент, який має властивість Mode(): string.

Я хотів би мати можливість встановити це властивість програмно, не відповідаючи на будь-яку подію.

Проблема полягає в тому, що за відсутності події веб-переглядача прив'язка шаблону {{Mode}}не оновлюється.

Чи є спосіб запустити виявлення цієї зміни вручну?

Відповіді:


640

Спробуйте один із таких:

  • ApplicationRef.tick()- подібний до AngularJS $rootScope.$digest()- тобто перевірити дерево компонентів
  • NgZone.run(callback)- аналогічно $rootScope.$apply(callback)- тобто, оцініть функцію зворотного виклику всередині кутової зони. Я думаю, але я не впевнений, що це закінчується перевіркою повного дерева компонентів після виконання функції зворотного виклику.
  • ChangeDetectorRef.detectChanges()- подібний $scope.$digest()- тобто перевіряйте лише цей компонент та його дітей

Ви можете вводити ApplicationRef, NgZoneабо ChangeDetectorRefв компонент.


1
Дякую, я вибрав 3-те рішення, щоб не перевірити все, оскільки зміни досить локалізовані. Я повинен вивчити інші варіанти, коли у мене буде більше часу. Чи є якісь наслідки для продуктивності при кожному виборі?
jz87

36
+1 для ChangeDetectorRef.detectChanges(). валідатори запускали, перш ніж моя директива могла оновити значення вводу.
ps2goat

7
ApplicationRef.tick () та ChangeDetectorRef.detectChanges () все ще присутні у фіналі 2.0.0.
Макс Мамфорд

51
Просто думав, що це згадаю. Це не статичні методи, це методи екземпляра. Вам потрібно буде ввести ці класи як послуги.
Стівен Пол

1
ApplicationRef.tick () допоміг вирішити проблему з FireFox v17 (<20)
Dan J

123

Я використав посилання на прийняту відповідь і хотів би навести приклад, оскільки документацію Angular 2 дуже важко читати, я сподіваюся, що це простіше:

  1. Імпорт NgZone:

    import { Component, NgZone } from '@angular/core';
    
  2. Додайте його до конструктора класу

    constructor(public zone: NgZone, ...args){}
    
  3. Запустити код за допомогою zone.run:

    this.zone.run(() => this.donations = donations)
    

6
куди слід поставити zone.runкод і що саме donations?
suku

@suku пожертви - це будь-яка власність, яку ви хочете оновити, тому це може бути this.foo = bar. zone.run відправляється туди, куди ви хочете оновити матеріали.
Метью Факультативний Механ

4
Я використовував це рішення, щоб змусити оновлення перегляду при використанні document.addEventListener ("відновити", зворотний виклик)
marcovtwout

71

Мені вдалося оновити його за допомогою markForCheck ()

Імпортуйте ChangeDetectorRef

import { ChangeDetectorRef } from '@angular/core';

Введіть і введіть його

constructor(private ref: ChangeDetectorRef) { 
}

Нарешті виявлення зміни позначки має відбутися

this.ref.markForCheck();

Ось приклад, коли markForCheck () працює, а detectChanges () не працює.

https://plnkr.co/edit/RfJwHqEVJcMU9ku9XNE7?p=preview

EDIT: Цей приклад більше не зображує проблеми :( Я вважаю, що це може бути запущена нова кутова версія, де вона виправлена.

(Натисніть STOP / RUN, щоб запустити його знову)


Точка Goo для detectChanges () не працює. Я помітив ту саму проблему і виявив, що вона працює, якщо для виявлення змін немає OnPush. Було б добре отримати пояснення для цього ...
Крістіан

2
Здається, що detectChanges насправді працює в цьому планку? Я щось пропускаю?
Jared_C

1
Слід зазначити, що ChangeDetectorRef працює лише в компонентах
kevinius

(!) Це поганий приклад, мені шкода. Приклад нічого не показує. Перший елемент просто перезапись. Просто налаштуйте таймери трохи ...
Пітер Стегнар

Цей приклад більше не зображує проблеми :( Я вважаю, що це може бути запущена нова кутова версія, де вона виправлена.
Nuno Tomas

7

У Angular 2+ спробуйте декоратор @ Input

Це дозволяє приємно зв'язувати властивості між батьківським і дочірнім компонентами.

Спочатку створіть глобальну змінну у батьків, щоб утримувати об’єкт / властивість, які будуть передані дитині.

Далі створіть у дитини глобальну змінну для зберігання переданого від батьків об'єкта / властивості.

Потім у батьківський html, де використовується дочірній шаблон, додайте позначення квадратних дужок із іменем дочірньої змінної, а потім встановіть його рівним імені батьківської змінної. Приклад:

<child-component-template [childVariable] = parentVariable>
</child-component-template>

Нарешті, де дочірнє властивість визначено в дочірньому компоненті, додайте декоратор введення:

@Input()
public childVariable: any

Коли ваша батьківська змінна оновлюється, вона повинна передавати оновлення дочірньому компоненту, який оновить його html.

Також, щоб запустити функцію в дочірньому компоненті, погляньте на ngOnChanges.


2
НЕ ... ось проблема ... якщо ви оновите в батьківській програмі ... скажімо, для exmaple оновлено "посиланням" в статичному методі, дитина не
зможе

У мене така ж проблема є вже цілі дні. Я намагаюся отримати дані з PHP бекенда, і дані зовсім не оновлюються. У Microsoft Edge працює чудово, але в інших браузерах - ні. Я продовжую отримувати дані, які я вперше почав, але якщо змінити дані, вони не оновлюються на перегляді
el6976

1

ChangeDetectorRef.detectChanges () - подібний до $ range. $ Digest () - тобто перевіряйте лише цей компонент та його дітей

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.