需要帮助修复角度2应用程序中的活动标签问题。
我正在加载来自json的标签和相应信息。
我有复杂的json格式,但在这里我制作了简化版本。
问题:在初始阶段未设置有效标签。
预期第一个标签'标签1'需要有效类。
请注意:点击标签页,活动课程已添加。 所以需要修复第一个元素的活动标签。所以我们应该干涉其他功能。
感谢任何帮助。
的Json
[
{
"id": "1",
"name": "Tabs 1",
"content": [
{
"header": "Basic Information",
"contents": [
{
"label": "Report 1"
}
]
}
]
},
{
"id": "2",
"name": "Tabs 2",
"content": [
{
"header": " Information",
"contents": [
{
"label": "Report 2"
}
]
}
]
},
{
"id": "3",
"name": "Tabs 3",
"content": [
{
"header": " report",
"contents": [
{
"label": "Report 3"
}
]
}
]
},
{
"id": "4",
"name": "Tabs 4",
"content": [
{
"header": " content Report",
"contents": [
{
"label": "Report 4"
}
]
}
]
}
]
应用-service.ts
import { Injectable } from '@angular/core';
import { Http, Response } from '@angular/http';
import { Observable } from 'rxjs/Observable';
import 'rxjs/add/operator/map';
import 'rxjs/add/operator/catch';
import 'rxjs/add/observable/throw';
@Injectable()
export class DashboardService {
private _url: string = "./app/report.json";
constructor(private _http: Http) {}
getRecords() {
return this._http.get(this._url)
.map((response: Response) => response.json())
}
_errorHandler(error: Response) {
console.error(error);
return Observable.throw(error || "Server Error");
}
}
app.component.ts
import {Component,ContentChildren,QueryList, OnInit,
Injectable, Inject} from '@angular/core';
import {TAB_COMPONENTS} from './tabset';
import {Tab} from './tab';
import { DashboardService } from './app-service';
@Component({
selector: 'my-app',
template: `
<h2>App Component</h2>
<tabset>
<tab *ngFor="let tab of records" [title]="tab.name">
<div *ngFor="let header of tab.content">
{{header.header}}
<div *ngFor="let label of header.contents">{{label.label}}</div>
</div>
</tab>
</tabset>
`
})
@Injectable()
export class AppComponent implements OnInit {
records = [];
errorMsg: string;
constructor(@Inject(DashboardService) private _dashboardService: DashboardService) {
//this.getRecords();
}
// getting json values from report.json
// To build the form
ngOnInit() {
this._dashboardService.getRecords()
.subscribe(
resGetRecords => {
debugger;
this.records = resGetRecords
},
resRecordsError => this.errorMsg = resRecordsError
);
}
}
tab.ts
import { Component, Input } from "@angular/core";
@Component({
selector: 'tab',
template: `
<ng-content *ngIf="active"></ng-content>
`
})
export class Tab {
@Input() title = '';
@Input() active = false;
@Input() disabled = false;
}
tabset.ts
import {
Component,
Input,
Output,
ContentChildren,
HostListener,
EventEmitter
} from '@angular/core';
import { Tab } from './tab';
@Component({
selector: 'tabset',
template: `
<section class="tab-set">
<ul
class="nav"
[class.nav-pills]="vertical"
[class.nav-tabs]="!vertical">
<li
*ngFor="let tab of tabs"
[class.active]="tab.active">
<a
(click)="tabClicked(tab)"
class="btn"
[class.disabled]="tab.disabled">
<span>{{tab.title}}</span>
</a>
</li>
</ul>
<div class="tab-content">
<ng-content></ng-content>
</div>
</section>
`
})
export class Tabset {
@Input() vertical;
@Output() onSelect = new EventEmitter();
@ContentChildren(Tab) tabs;
ngAfterContentInit() {
const tabs = this.tabs.toArray();
const actives = this.tabs.filter(t => {
return t.active
});
if (actives.length > 1) {
console.error(`Multiple active tabs set 'active'`);
} else if (!actives.length && tabs.length) {
tabs[0].active = true;
}
}
tabClicked(tab) {
const tabs = this.tabs.toArray();
tabs.forEach(tab => tab.active = false);
tab.active = true;
this.onSelect.emit(tab);
}
}
export const TAB_COMPONENTS = [
Tabset,
Tab
];
答案 0 :(得分:1)
编辑:我认为答案最终与您的问题不相似。遗憾。
- 如果您使用角度4 -
您可以看到类似的issue that I have reported。
有一个黑客可以让它发挥作用:
[routerLinkActive]="['']" [ngClass]="rla.isActive?'active':''" #rla="routerLinkActive"
答案 1 :(得分:0)
如果你没有从json加载数据,它会起作用,我的意思是你需要等待一个异步行为。
第一次使用空数组records = [];
初始化标签(在 app.component.ts 中)
在tabset组件中,在 ngAfterContentInit 中,您只检查此时为空数组的第一个选项卡数据,并使用第一个选项卡初始化选项卡集,该选项卡在此时间为<强>未定义即可。因此没有选项卡设置为活动,这就是没有选定选项卡的原因。
选项卡数据将使用正确的内容((来自json的4项)更新)仅在加载JSON数据时,订阅http后,并且没有检查和设置默认选定选项卡的操作
因此,您的解决方案是在设置选定的标签之前订阅标签中的更改:
ngAfterContentInit() {
this.tabs.changes.subscribe((changes)=> {
const tabs = this.tabs.toArray();
const actives = this.tabs.filter(t => {
return t.active
});
if (actives.length > 1) {
console.error(`Multiple active tabs set 'active'`);
} else {
this.tabClicked(tabs[0]);
}
});
}
<强>此外:强>
如果您遇到如下错误:
Expression has changed after it was checked. Previous value: 'false'. Current value: 'true'.
您需要添加the angular doc here
中描述的setTimeout()
ngAfterViewInit()生命周期钩子是一个重要的皱纹。该 在Angular显示之后,计时器组件才可用 父视图。所以它最初显示0秒。然后Angular调用 ngAfterViewInit生命周期钩子,此时为时已晚 更新父视图的倒计时秒显示。角的 单向数据流规则可防止更新父视图 同样的周期。该应用必须等待一转才能显示 秒。
使用setTimeout()等待一个tick,然后修改seconds()方法 这样就可以从计时器组件中获取未来的值。
现在:
tabClicked(tab) {
const tabs = this.tabs.toArray();
tabs.forEach(tab => tab.active = false);
setTimeout( () => tab.active = true);
this.onSelect.emit(tab);
}