почему получение фокуса запускает привязку данных в angular 5?

При разработке мультикультурного приложения Angular5 я структурировал класс, который содержит словарь (пользовательский класс ts) для хранения переводов. Когда пользователь меняет культуру, все, что с ней связано, должно измениться. Это работает, но… слишком много.

Поскольку я использую console.log каждый раз, когда вызывается метод, который получает правильное предложение в соответствии с выбранной культурой, я заметил, что если я просто нажимаю на текстовое поле, Angular обновляет все и, что непонятно, если я ничего не нажимаю вскоре после того, как просто оставьте фокус, снова angular все обновляет! Я знаю, что должно быть что-то связанное с ChangeDetectionStrategy, но я безуспешно пытался решить эту проблему.

Когда приложение вырастет, если браузеру придется каждый раз все перезагружать... какая проблема! Приложение выглядит так:

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

Главный контроллер выглядит так:

@Injectable()
export class MainController extends BaseClass {
    private currentCulture: string;
    private platformLocalizedSentencies: KeyedCollection<LocalizedString>;

класс LocalizedString выглядит так:

@Injectable()
export class LocalizedString extends BaseClass {
    public DefaultText: string;
    public IdTranslationIndex: number;
    public Translations: KeyedCollection<string>;

    constructor() {
        super();
        this.Translations = new KeyedCollection<string>();
    }

    public GetTranslation(culture: string) {
        console.log('getting translation for ' + this.DefaultText + ' in culture ' + culture);

        if (!this.Translations.ContainsKey(culture)) {
            return '*' + this.DefaultText;
        } else {
            return this.Translations.Item(culture);
        }
    }
}

Теперь есть компонент (culture-selector.component.ts), который показывает флаги (changeDetection: ChangeDetectionStrategy.OnPush), и когда пользователь выбирает флаг, это происходит:

onCultureClick(menuItem: string) {
    console.log(menuItem + ' clicked.');
    this.mainController.CurrentCulture = menuItem; // this must be the thing which unleash the databinding on the other components I think and I hope
    this.updateSelectedCultureUI(); // doesn't do anything special, just sets the right flag and culture name on the top of the control
    this.mainController.trace(TraceType.Info, 'Culture ' + this.cultureName + ' clicked');
  }

и компонент, где я заметил чертову дикость по привязке данных, компонент входа в систему:

@Component({
  selector: 'app-login',
  templateUrl: './login.component.html',
  styleUrls: ['./login.component.css'],
})

export class LoginComponent extends BaseClass implements OnInit, AfterViewInit {
constructor(public mainController: MainController) { 
    super();
  }

ngOnInit() {
    this.usernamePlaceholder = this.mainController.PlatformLocalizedSentencies.Item('Username');

Теперь «usernamePlaceholder» используется в html следующим образом:

<mat-form-field style="width: 100%;">
            <input matInput [placeholder]="usernamePlaceholder.GetTranslation(mainController.CurrentCulture)" [(ngModel)]="loginInput.username" (keypress)="eventHandler($event.keyCode, 'txtUsername')" #txtUsername>
</mat-form-field>

на следующем рисунке вы можете увидеть в окне консоли, что произойдет, если я просто щелкну текстовое поле имени пользователя .... Я очистил консоль перед щелчком. Что здесь происходит? Я потратил два дня, пытаясь понять... извините, это мое первое угловое приложение.. Я должен был начать с чего-то попроще :)

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

.... и метод получения правильной строки

 public GetPlatformSentence(key: string) {
        console.log('getting translation for ' + key + ' in culture ' + this.CurrentCulture);

        if (!this.PlatformLocalizedSentencies.ContainsKey(key)) {
            return '[NOTRANSLATION]';
        }
        if (!this.PlatformLocalizedSentencies.Item(key).Translations.ContainsKey(this.CurrentCulture)) {
            return '*' + this.PlatformLocalizedSentencies.Item(key).DefaultText;
        } else {
            return this.PlatformLocalizedSentencies.Item(key).Translations.Item(this.CurrentCulture);
    }

}

Все равно спасибо

вот что происходит


person Fabio Infante    schedule 05.01.2018    source источник


Ответы (1)


Хорошо, ребята, я пробовал что угодно, но безуспешно. Угловая привязка... слишком педантична :-) Лучший результат, которого мне удалось добиться, это обновление при первом взаимодействии с пользователем. Поэтому мне пришлось выбирать между обновлением всего каждый раз (что было слишком много) или обновлением, как только пользователь щелкнул где-нибудь, принудительно обновив привязку (это то, что я смог получить, играя с настройками ChangeDetectionStrategy и некоторым дополнительным кодом).

Поэтому я решил (только для непосредственной привязки multicuture) с помощью messageService. Каждый компонент подписывается и запрашивает общий майконтроллер для обновления всего, что связано с культурой, когда она изменяется. Конечно, мне нужно было написать немного больше кода, но результат с точки зрения пользовательского опыта, скорости отклика и загрузки процессора очень и очень хорош. Также исполняемый код одинаков для каждого компонента, так что это не так уж и плохо.

Конечно, это не то, что я ожидал, но это работает лучше для меня.

person Fabio Infante    schedule 23.01.2018