2016-12-02 3 views
2

На самом деле есть две проблемы, с которыми я сталкиваюсь. Я перекручивание через массив значений и нужноAngular2: Установить класс CSS из Observable

  1. установить имя класса в зависимости от наблюдаемой переменной из дочернего компонента.
  2. переоценить класс, как только изменяется дочерняя переменная.

location.component.ts

import { Component, Input } from '@angular/core'; 

import { BusinessLocation, SpecialDays, RegularHours } from './location'; 
import { DbService } from './db-service.component'; 

@Component({ 
    selector: '[data-locations]', 
    templateUrl: 'app/location.component.html', 
    providers: [DbService] 
}) 

export class LocationComponent { 

    locations:BusinessLocation[]; 
    selectedLocationId:Number; 
    constructor(private api:DbService){} 

    isOpenOnDay(day):Boolean { 

     let _weekDay = day.getDay(); 
     let _retour = false; 

     this.locations.forEach(loc => { 
     if (loc.id == this.selectedLocationId && loc.regularHours.weekDay == _weekDay) { 
      _retour = true; 
     } 
     }); 

     this.locations.forEach(loc => { 
     if (loc.id == this.selectedLocationId && loc.specialDays.singleDate.getDay() == _weekDay) { 
      _retour = true; 
     } 
     }); 

     return _retour; 
    } 

    getLocation():Number { 
     return this.selectedLocationId; 
    } 

    setLocation(id):void { 
     this.selectedLocationId = id; 
    } 

    getLocations():void { 
     this.api.getLocations().subscribe(
      locations => { 
      this.locations = locations as BusinessLocation[]; 
      this.setLocation(this.locations[0].id); 
      } 
     ); 
    } 

} 

фрагмент из DB-services.component.ts

getLocations():Observable<BusinessLocation[]> { 
     return this.http.get(this.apiUrl + '/get_locations.php') 
         .map(response => response.json().data as BusinessLocation[]); 
    } 
} 

все работает отлично. Однако здесь есть проблема. Родительский компонент инициирует местоположения, но он также должен знать, какое местоположение выбрано прямо сейчас. Вот month.component.html

<span class="location-container" #location data-locations><span class="loading">Loading locations...</span></span> 

     <div *ngFor="let day of week.days" class="day" data-can-drop="day" 
      [class.today]="isToday(day)" 
      [class.in-other-month]="day.getMonth() != jsMonth" 
      [class.is-closed]="!isOpenAtLocation(day)"> 
      <div class="day-marker"></div> 
      <span class="day-date">{{day | date:'d'}}</span> 
      <span *ngIf="checkMonth(day)" class="day-month">{{months[day.getMonth()]}}</span> 
     </div> 

и фрагмент из month.component.ts является

@ViewChild('location') locationComponent:LocationComponent; 

    isOpenAtLocation(day):Boolean { 
    return this.locationComponent.isOpenOnDay(day); 
    } 

    ngOnInit(): void { 
    this.locationComponent.getLocations(); 
} 

Я получаю ошибку довольно просто и вполне понятно:

Subscriber.ts:238 TypeError: Cannot read property 'forEach' of undefined 
    at LocationComponent.isOpenOnDay (location.component.ts:25) 
    at MonthComponent.isOpenAtLocation (month.component.ts:176) 

И это как раз о вызове 1. Задача 2 еще не была рассмотрена.

Я просто не могу обернуть вокруг себя голову. > _ < Спасибо.

ответ

1

Ну, это была плохая шутка на моей стороне. Во-первых, это напоминание о том, что изменение свойства объекта будет отражать себя в DOM, если имеется привязка. Таким образом, общее число [class.isOpenOnDay]="day.isOpenAtLocation" было бы вполне достаточным, где day является объектом и isOpenAtLocation является его собственностью. Даже если он не установлен первоначально (то есть это null) и будет обновляться в будущем - все хорошо. В основном это работает NG (и работал все время). Дурак я.

Другая проблема - изменение значения в зависимости от дочерней компонентной переменной - была решена путем испускания событий (от дочернего), прослушивания событий (в родительском) и повторного сброса свойства isOpenAtLocation.

Так Обновленные дочерние компоненты location.component.ts был обновлен, как это:

@Output() locationChanged = new EventEmitter<Number>(); 

setLocation(id):void { 
    this.selectedLocationId = id; 
    this.locationChanged.emit(this.selectedLocationId); 
} 

Представления для компонента местоположения теперь имеет следующую строку:

<select (change)="setLocation($event.target.value)"> 
<option *ngFor="let loc of locations" value="{{loc.id}}">{{loc.longName}}</option> 
</select> 

Родитель компоненту вид связан со следующим событием:

<span class="location-container" #location data-locations (locationChanged)="onLocationChange($event)"><span class="loading">Loading locations...</span></span> 

И родитель month.component.Сам ц имеет еще два метода:

onLocationChange(event) { 
    if (this.selectedLocationId != event) { 
     this.selectedLocationId = event; 
     this.setLocation(); 
     this.dispatchResize(); 
    } 
    } 

    setLocation():void { 

    if (this.selectedLocationId >= 0) { 

     for (let i = 0; i < this.weeks.length; i++) { 
     let _week = this.weeks[i]; 

     _week.forEach(_day => { 
      let _isOpen = this.locationComponent.isOpenOnDay(_day.date); 
      _day['isOpenOnDay'] = _isOpen.isOpenOnDay; 
      _day['isSpecialDay'] = _isOpen.isSpecialDay; 
      _day['dayHours'] = _isOpen.dayHours; 
     }); 

     } 

    } 

    } 

Как можно видеть, я добавил еще более динамично проверяются свойства, а не только isOpenOnDay, но и isSpecialDay и dayHours, которые еще не определены изначально, но устанавливаются как в скором времени, когда данные будут доступны, и они отражаются в поле зрения сразу же после их изменения.

Основные вещи, на самом деле. Все еще может быть полезно для некоторых NG2 noob, подобных мне.

Смежные вопросы