Angular 2 - Warum brauche ich zone.run ()?

Ich versuche, in Angular 2 eine Komponente zu erstellen, die Daten von einem Dienst anzeigt. Der Dienst lädt grundsätzlich einige Daten aus einer JSON-Datei, nachdem der Benutzer sie eingegeben hat. Ich habe versucht, die Komponente auf den neuesten Stand zu bringen, aber es scheint keine Änderungen zu erkennen, es sei denn, ich rufe zone.run () auf, nachdem ich ein Ereignis von meinem Dienst gesendet habe. Mein Code ist wie folgt für die Komponente ...

@Component({
    selector: 'assess-asset-group',
    directives: [AssetComponent, AssetHeaderComponent, NgFor, NgIf],
    template: `

            <div *ngIf="assetService.schema != null">
                <div class="asset-group" *ngFor="#assetTypeName of assetService.schema.assetTypeNames"> 
                    <div class="asset-type-title"><span>{{assetService.schema.assetTypes[assetTypeName].name}}s</span></div> 
                    <table class="asset-group-table" cellpadding=0 cellspacing=0>
                        <thead>
                            <tr assess-asset-header [assetType]="assetService.schema.assetTypes[assetTypeName]"></tr>
                        </thead>
                        <tbody>
                            <tr assess-asset *ngFor="#asset of assetService.assetsForType(assetTypeName)" [asset]="asset"></tr>
                        </tbody>
                    </table>
                    <button class="new-asset-btn" (click)="assetService.addAsset(assetTypeName)">New</button>
                </div>
            </div>`,
    providers: [provide(AssetService, {useValue: injector.get(AssetService)})]
})
export class AssetGroupComponent {

    public assetService: AssetService;
    public zone: NgZone;

    constructor( @Inject(AssetService) assetService: AssetService, zone: NgZone) {
        this.assetService = assetService;
        this.zone = zone;
    }

    ngOnInit() {
        this.assetService.proejectLoadedEmitter.subscribe((e) => { this.zone.run(() => { }) });
    }

    ngOnDestroy() {
        this.assetService.proejectLoadedEmitter.unsubscribe();
    }
}

Mache ich etwas falsch oder ist dies das, was ich tun muss, um die Ansicht zu aktualisieren?

UPDATE - AssetService-Klasse

@Injectable()
export class AssetService{
    public assets: Assets.Asset[] = [];
    public assetTypeDefinitions: any = null;

    public schema: Schema = null;
    public assetsAsObj: any = null; // Asset file loaded as object

    @Output() proejectLoadedEmitter: EventEmitter<any> = new EventEmitter();

    constructor(){
    }

    public loadProject(config: Project){
        // Load schema
        // populate AssetTypeDefinitions as object keyed by type
        let data = fs.readFileSync(config.schemaPath, 'utf8');
        if (!data) {
            utils.logError("Error reading schema file");
            return;
        }
        let struc = fs.readFileSync(config.structurePath, 'utf8');
        if (!struc) {
            utils.logError("Error reading structure file");
            return;
        }

        this.schema = new Schema(JSON.parse(data), struc);
        this.readAssets(config.assetFilePath);
    }

    /**
     * @brief Adds a new asset to the assets array 
     * @details Constructs the asset based on the type and populates
     *  its fields with appropreiate default values
     * 
     * @param type The type of the asset - specified in the schema
     */
    public addAsset(type: string): void {
        // Need to make sure there is a loaded type definition for the specified type
        if(!this.schema.assetTypes.hasOwnProperty(type)){
            utils.logError("Error occured during call to addAsset - type \"" + type + "\" is not specified in the loaded schema");
            return;
        }
        // Creeate a new asset object - passing in the type definition from the schema
        this.assets.push(new Assets.Asset(this.schema.assetTypes[type]));
    }   

    /**
     * Write the current assets to a file using the specified format
     * If the outputPasth isn't specied try and load it from the project.json file
     */
    public writeAssets(format:AssetWriteFormat, outputPath?: string) : void {

        var outStructureStr = this.schema.structureStr;
        // insert AS properties from schema into output assets
        this.schema.properties.forEach(prop => {
            outStructureStr = outStructureStr.replace(new RegExp('"' + prop +'"', 'i'), this.retriveValueForSchemaProperty(prop));
        });

        fs.writeFileSync("C:/Projects/Assess/assets.json", outStructureStr);
    }

    public readAssets(inputPath?: string) : void{
        let assetsStr = fs.readFileSync(inputPath, 'utf8');

        let strucToAssetMap = {};
        let strucObj = JSON.parse(this.schema.structureStr);
        this.schema.properties.forEach(p => {
            strucToAssetMap[p] = this.findValueInObject(strucObj, p).reverse();
        });

        // @TODO Load custom properties
        let assetsObj = JSON.parse(assetsStr);
        var c = null;
        strucToAssetMap["AS_ASSETS"].forEach(p => {
            if(c == null){
                c = assetsObj[p];
            }else{
                c = c[p];
            }
        });
        c.forEach((asset) => {
            let a:Assets.Asset = new Assets.Asset(this.schema.assetTypes[asset.type], asset);
            this.assets.push(a);
        });
        console.log(this.assets);
        this.proejectLoadedEmitter.emit(null);
    }

    public assetsForType(type:string): Assets.Asset[]{
        var ret: Assets.Asset[] = [];
        for(let idx in this.assets){
            if(this.assets[idx].definition.type === type){
                ret.push(this.assets[idx]);
            }
        }
        return ret;
    }

    public retriveValueForSchemaProperty(property: string) : string{
        if(AS_SchemaTypes.indexOf(property) != -1){
            switch (property) {
                case "AS_ASSETS":
                    let outAssets = [];
                    this.assets.forEach((asset) => {
                        let outAsset = {};
                        outAsset["type"] = asset.definition.type;

                        for (let key in asset.fields) {
                            outAsset[key] = asset.fields[key].value;
                        }
                        outAssets.push(outAsset);
                    });
                    return JSON.stringify(outAssets, null, "\t");
            }
        }else{
            // @TODO Retrive custom properties
            return '"DDDDDD"';
        }
        return "";
    }

    public findValueInObject(obj: any, property: string, path: any[] = []): any[] {
        for(let x in obj){;
            let val = obj[x];
            if (val == property){
                path.push(x);
                return path;
            }
            else if(val != null && typeof val == 'object'){
                let v = this.findValueInObject(val, property, path);
                if(v != null){
                    path.push(x);   
                    return path;
                }
            }
        }
        return null;
    }
}