Как заставить метод фильтра выбора даты в календаре материала работать с наблюдаемыми - PullRequest
3 голосов
/ 16 января 2020

Я использую приложение Angular Material Date Picker в своем проекте, которое является формой бронирования. Я хочу, чтобы пользователь выбрал дату с помощью Date Picker . Выбор даты будет иметь фильтр, который покажет, какие даты открыты, а какие нет. Чтобы сборщик дат знал, какие даты доступны, он должен позвонить в одну из моих служб, которая возвращает Observable . Вот мой код HTML для средства выбора даты:

<mat-form-field>
  <label>
    <input matInput [matDatepickerFilter]="dateFilter" required [matDatepicker]="picker" placeholder="Choose a date"
           formControlName="date">
  </label>
  <mat-datepicker-toggle matSuffix [for]="picker"></mat-datepicker-toggle>
  <mat-datepicker #picker></mat-datepicker>
</mat-form-field>

и dateFilter ():

dateFilter = (d: Date): boolean => {
    if(monthIsSame(d) {
        ..// have a return statement that process a global variable: 'month: Day[]'
    } else {
        // the user hit the arrow at the top that switches months
        //
        // have a process that sets the 'month' variable to a new array of Days that was gotten 
        // through a RESTful api in one of my services.
        // Somehow there must be a loading wheel here until the result from my server comes back and
        // month is set to the new current month, and then a return statement that process a month
    }
};

Проблема заключается в том, что каждый раз, когда пользователь переключает месяцы, календарь должен загружать месяц доступности с задней стороны сервера, но код с сервера возвращает Observable. Каким-то образом в календаре должно отображаться колесо загрузки, пока значение не возвращается из метода подписки наблюдаемого, и календарь будет заполнен доступными датами.

Любая помощь очень ценится, и если я приду к этому совершенно неправильным путем, пожалуйста, скажите мне. Спасибо!


Изменения:

Примечание: когда я изменяю тип возврата моего фильтра на Observable<boolean>, он устанавливает все доступные даты.

Я нашел следующую запись . Было бы как-то возможно иметь функцию обратного вызова, которая вызывается, когда пользователь переключает месяцы, запускает мой http-запрос и загружает результаты в локальную переменную. Единственная проблема заключается в том, что календарь должен показывать колесо загрузки, пока не завершится функция обратного вызова.

Ответы [ 3 ]

1 голос
/ 21 января 2020

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

Вам понадобится сервис для передачи данных между вашим пользовательским заголовком (подробности за минуту) и вашей страницей. компонент, где у вас есть метод dateFilter. Давайте назовем эту услугу OpenDatesService. Я думаю, что его не следует предоставлять в модуле, потому что он не всегда нужен, но он должен иметь как минимум такой же жизненный цикл, как и ваша страница, поэтому в идеале он должен быть представлен на вашей странице. В этом случае вы сможете внедрить как компонент страницы, так и свой пользовательский заголовок, и это будет один и тот же экземпляр.

Поэтому создайте пользовательский заголовок. Вы можете полностью взять тот из Angular Material или пример из документов . Я объясню, используя этот пример. В предыдущих / следующих обратных вызовах заголовка вы не сразу вызываете календарь (_dateFormats в примере), но сначала запускаете сетевой запрос, заменяете стрелки на счетчик (используйте флаг и некоторые ngIf с) и только повторно включите кнопки после того, как сетевой запрос вернулся. Да, это asyn c (наблюдаемые / обещание / asyn c -wait), но на этом этапе вы не обязаны делать что-то синхронно. Поэтому после завершения сетевого запроса, но еще до вызова метода prev / метода календаря, передайте данные открытых дат в OpenDatesService, ie. у него должен быть метод sg. как updateOpenDates. Затем вы можете вызвать метод prev / next календаря.

После вызова метода prev / next календаря скоро будет вызван компонент dateFilter компонента вашей страницы. Но к этому времени OpenDatesService будет иметь данные с датами открытия, и сервис будет добавлен на страницу, поэтому в dateFilter вы можете просто получить его синхронно, а синхронно вернуть основанный на нем результат в календаре.

Итак, для подведения итогов есть 2 хитрости:

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

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

Сейчас Я думаю, вам даже не нужен этот сервис для передачи данных между пользовательским заголовком и компонентом страницы. Это связано с тем, что пользовательский заголовок создается в шаблоне компонента страницы, где заголовок может просто передавать данные на страницу с @Output, а страница может сохранять их в некоторых локальных полях, которые также доступны для dateFilter метод.

1 голос
/ 15 марта 2020

Как сделать так, чтобы мат-календарь обновлял sh фильтр даты асинхронно:

Решение состоит в том, чтобы установить dateFilter в новое значение при получении данных с сервера. Angular проверяет это значение при обнаружении изменений и обновляет представление.

// initial filter function always returns true
dateFilter = (date: Date): boolean => {return true;}

constructor( ... ) {

  this.myDataObs.subscribe( () => {
    // set filter function when new data is available
    this.dateFilter = (date: Date): boolean => { 
      return filterBasedOnDataFromServer(date);
    };
  });
}
0 голосов
/ 16 января 2020

Я не уверен в части колеса загрузки (может быть, поставить флажок на компонент и установить его внутри трубы до и после вашего сервисного вызова?)

Но с точки зрения проблемы возврата Очевидно, я думаю, что ваша проблема может быть решена с помощью канала async:

[matDatepickerFilter]="dateFilter | async"

, который будет автоматически обрабатывать подписку и отписку. Просто убедитесь, что вы поставили shareReplay(1) после вызова API, иначе вызов API будет срабатывать при каждом цикле обнаружения изменений (что может быть довольно часто).

...