изменение значения подписки angular 2 не отражается на html

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

Доработанная версия Angular 2

Цель: скрыть / показать меню навигации на основе ролей. Подход: я использую Facebook для аутентификации пользователей. После аутентификации будут извлечены роли пользователей, которые будут использоваться для определения необходимости отображения меню администратора. Вызов observable.next выполняется со значением true, и подписка на компонент панели навигации подхватит флаг и изменит isAdmin на true. (IsAdmin изначально имеет значение false). Это позволит отображать меню администратора.

Проблема: подписчик правильно подбирает флаг true, а для isAdmin установлено значение true. Однако меню администратора не отображается.

navbar.component.ts

@Component({
selector: 'as-navbar',
templateUrl: 'app/shared/navbar/navbar.html',
changeDetection: ChangeDetectionStrategy.OnPush
})
export class NavbarComponent {
@Input() brand: string;
public isAdmin:boolean;

constructor(private _securityService:SecurityService){
    let self = this;

    this._securityService.isAdminObservable.subscribe(function (flag) {
        this.isAdmin = flag;
        console.log('subscribe received on navbar');
    }.bind(this));
 }
}

navbar.html

        <li class="dropdown" *ngIf="isAdmin">
      <a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false">Admin<span class="caret"></span></a>
      <ul class="dropdown-menu">
        <li><a [routerLink]="['/campaigns']">Campaigns</a></li>
        <li><a [routerLink]="['/products']">Products</a></li>
        <li><a [routerLink]="['/products']">Reports</a></li>
      </ul>
    </li>

app.component.ts

    constructor(private _http: Http, private _jsonp: Jsonp, private _securityService:SecurityService) {
    this.appBrand = CONSTANTS.MAIN.APP.BRAND;

    let self = this;
    setInterval(function(){
        self._securityService.setAdminStatus(true);
        console.log('set from app component');
    }, 5000)
}

security.service.ts

@Injectable()
export class SecurityService{
public isAdmin:Subject<boolean>=new Subject<boolean>();
public isAdminObservable = this.isAdmin.asObservable();

constructor(){}

setAdminStatus(flag){
    this.isAdmin.next(flag);
    }
}

Что-то не так? Или есть лучший подход к достижению цели? Любое предложение будет принято с благодарностью! Спасибо

ОБНОВЛЕНИЕ

Получив ответ от peeskillet, я удалил строку changeDetection из компонента, и она работает.

Однако, когда я продолжаю работать над кодом, я перемещаюсь

self._securityService.setAdminStatus(isAdmin);

в другую службу (в данном случае службу Facebook) и вызовите эту службу из компонента приложения. Подписка в navbar.compoenent.ts принимает изменение, но не запускает обнаружение изменений. Мне нужно вручную запустить обнаружение, чтобы оно сработало.

обновлен navbar.component.ts

@Component({
selector: 'as-navbar',
templateUrl: 'app/shared/navbar/navbar.html'
})
export class NavbarComponent {
@Input() brand: string;
public isAdmin:boolean=false;

constructor(private _securityService:SecurityService, private cdr: ChangeDetectorRef){
    this._securityService.isAdminObservable.subscribe(function (flag) {
            this.isAdmin = flag;
            this.cdr.detectChanges();
            console.log('subscribe received on navbar');
        }.bind(this));
    }
}

обновлен app.component.ts

@Component({
    selector: 'as-main-app',
    templateUrl: 'app/app.html'
})
export class AppComponent {
    public appBrand: string;
    constructor(private _http: Http,
            private _facebookService:FacebookService
) {
        this.appBrand = CONSTANTS.MAIN.APP.BRAND;
        this._facebookService.GetLoginStatus();
    }
}

Это довольно интересно. По-видимому, мне нужно узнать больше об обнаружении изменений angular 2. Если кто знает хорошую ссылку, поделитесь, пожалуйста, со мной.

Спасибо!!




Ответы (1)


Это потому, что вы используете changeDetection: ChangeDetectionStrategy.OnPush. Это означает, что обнаружение изменений для компонента будет происходить только тогда, когда изменяются входные данные @Inputs 1.

Так что, если вы удалите @Component.changeDetection, он должен работать.

Если ваша цель - сохранить стратегию OnPush, тогда одним из вариантов будет явное принудительное обнаружение изменений с помощью ChangeDetectorRef

class SomeComponent {
  message;

  constructor(private service: Service, private cdr: ChangeDetectorRef) {
  }

  ngOnInit() {
    this.service.subscribe(data => {
      this.message = data;
      this.cdr.detectChanges();
    })
  }
}

1 - см. также ChangeDetectionStrategy.OnPush и Observable.subscribe в Angular 2

person Paul Samsotha    schedule 08.10.2016
comment
Это круто! Спасибо за ответ. Я удалил changeDetection: ChangeDetectionStrategy.OnPush, и код заработал! Интересная штука есть. Я переместил логику в другую службу. (Служба Facebook) Когда Facebook возвращает информацию о пользователе, я затем беру роли из базы данных, а затем next () флаг. Подписчик получил его, но изменения не обнаружено. Мне все еще нужно вручную запускать changeDetection, чтобы он работал. Интересно, почему. Я обновил код. - person Chuck; 08.10.2016
comment
Да, я не уверен. - person Paul Samsotha; 08.10.2016
comment
Что касается вашего комментария в нижней части вашего сообщения, вот отличный справочник - person Paul Samsotha; 08.10.2016
comment
В Angular 9 в блоке subscribe() мне также пришлось использовать вызов метода detectChanges(), чтобы сработало обнаружение изменений и обновилось представление. - person Stephane; 20.03.2020