Angular2:从Observable设置CSS类

时间:2016-12-02 18:09:11

标签: css angular typescript promise observable

实际上我面临两个挑战。我循环遍历一系列值,需要

  1. 根据子项中的可观察变量设置类名 零件。
  2. 一旦子变量发生变化,就会重新评估该类。
  3. 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尚未得到解决。

    我无法绕过它。 &GT; _&LT; 感谢。

1 个答案:

答案 0 :(得分: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.ts 本身还有两个方法:

  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菜鸟来说,仍然可能会有所帮助。