Angular2: Изменение класса таба через ElementRef

Возвращаясь к прошлому примеру — в изменении не хватает активации пункта меню (вернее она есть — но мы не сможем с ней работать если нужно .active дописать к элементу li

<h1>{{title}}</h1>
<ul>
<li><a [routerLink]="['/data']" routerLinkActive="active">{{ 'Data' }}</a></li>
<li><a [routerLink]="['/contacts']" routerLinkActive="active">{{ 'Contacts' }}</a></li>
</ul>

Повторение пройденного

Наивно полагая, что мы можем использовать прошлый код и ngClass директиву, мы добавляем так же как и тайтл в прошлом примере таб в данные между компонентами.

class ContactsComponent {
	ngOnInit() {
		...
		this.appTitleService.setTab('contacts');
		...
	}
}
....
@Injectable() class AppComponentTitleService {
        public currentTab: Subject<any>=new Subject();
        public setTab(tab) {
		this.currentTab.next(tab);
	}
}
...
class AppComponent {
	public tab: string = 'some_tab';
 
	constructor(private appTitleService: AppComponentTitleService) {
		AppTitleService.currentTab.subscribe(tab=>this.tab=tab);
	}
}
<h1>{{title}}</h1>
<span>to check working or not {{tab}}</span>
<ul>
<li [ngClass]="{active: tab=='data'}"><a [routerLink]="['/data']" routerLinkActive="active">{{ 'Data' }}</a></li>
<li [ngClass]="{active: tab=='contacts'}"><a [routerLink]="['/contacts']" routerLinkActive="active">{{ 'Contacts' }}</a></li>
</ul>

Мое удивление и разочарование было безграничным ибо классы отрисовывались с задержкой в один клик, т.е. значение менялось в поле tab, в шаблоне обновлялось {{tab}}, но связанное действие на класс опаздывало до следующей отрисовки. Добавление тестовых контроллеров в роутер показало что проблема хоть и мелкая — но гаденькая (пользователь явно будет опечален)

Изменение класса элемента в DOM и Angular2

Пришлось прибегнуть к тому, от чего очень отговаривает официальная документация — прямому манипулированию html тегами на странице. Для этого инициализируем элемент в компоненте (рутовый элемент, к которому компонент привязан)

import { Component, ElementRef } from '@angular/core';
import { ROUTER_DIRECTIVES } from '@angular/router';
import { AppComponentTitleService } from  '../app/app.component.title.service';
 
@Component({
	selector: 'my-app',
	templateUrl : 'js_parts/app/app.component.html',
	directives: [ROUTER_DIRECTIVES],
	providers: [AppComponentTitleService,
})
 
class AppComponent {
	public tab: string = 'some_tab';
 
	constructor(private el : ElementRef,private appTitleService: AppComponentTitleService) {
		appTitleService.currentTab.subscribe(tab=>this.tab=tab);
	}
}
export {AppComponent};

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

import { Component, ElementRef } from '@angular/core';
import { ROUTER_DIRECTIVES } from '@angular/router';
import { AppComponentTitleService } from  '../app/app.component.title.service';
 
@Component({
	selector: 'my-app',
	templateUrl : 'js_parts/app/app.component.html',
	directives: [ROUTER_DIRECTIVES],
	providers: [AppComponentTitleService,
})
 
class AppComponent {
	public tab: string = 'some_tab';
 
	constructor(private el : ElementRef,private appTitleService: AppComponentTitleService) {
		appTitleService.currentTab.subscribe(tab=>this.setTab(tab));
	}
        setTab(tab) {
		if (this.tab != 'some_tab') {
			this.el.nativeElement.querySelector('li.active').className = '';
		}
		this.tab=tab;
		this.el.nativeElement.querySelector('li#tab_' + tab).className = 'active';
	}
}
export {AppComponent};
<h1>{{title}}</h1>
<span>to check working or not {{tab}}</span>
<ul>
<li id="tab_data"><a [routerLink]="['/data']">{{ 'Data' }}</a></li>
<li id="tab_contacts"><a [routerLink]="['/contacts']">{{ 'Contacts' }}</a></li>
</ul>

Оставить комментарий

XHTML: Вы можете использовать такие теги: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong> <pre lang="" line="" escaped="" cssfile="">