Each time we want to update the UI we are forced to use the zone.run() method and this in not an option since it's unintuitive and force devs to add more repetitive code.
Here our main dependencies:
"dependencies": {
"@angular/animations": "4.0.0",
"@angular/common": "4.0.0",
"@angular/compiler": "4.0.0",
"@angular/compiler-cli": "4.0.0",
"@angular/core": "4.0.0",
"@angular/forms": "4.0.0",
"@angular/http": "4.0.0",
"@angular/platform-browser": "4.0.0",
"@angular/platform-browser-dynamic": "4.0.0",
"@angular/platform-server": "4.0.0",
"@angular/router": "4.0.0",
"@angular/upgrade": "4.0.0",
"@types/electron": "^1.4.34",
Here a snippet of our index.html :
<!-- 1. Load libraries -->
<script src="../node_modules/zone.js/dist/zone.js"></script>
<script src="../node_modules/reflect-metadata/Reflect.js"></script>
<script src="../node_modules/systemjs/dist/system.src.js"></script>
<!-- 2. Configure SystemJS -->
<script src="systemjs.config.js"></script>
<script>
System.import('app').catch(function(err){ console.error(err); });
</script>
Here the systemjs.config.js relevant part
(function (global) {
System.config({
paths: {
// paths serve as alias
'npm:': '../node_modules/'
},
// map tells the System loader where to look for things
map: {
// our app is within the app folder
app: 'app',
// angular bundles
'@angular/core': 'npm:@angular/core/bundles/core.umd.js',
'@angular/common': 'npm:@angular/common/bundles/common.umd.js',
'@angular/compiler': 'npm:@angular/compiler/bundles/compiler.umd.js',
'@angular/platform-browser': 'npm:@angular/platform-browser/bundles/platform-browser.umd.js',
'@angular/platform-browser-dynamic': 'npm:@angular/platform-browser-dynamic/bundles/platform-browser-dynamic.umd.js',
'@angular/http': 'npm:@angular/http/bundles/http.umd.js',
'@angular/router': 'npm:@angular/router/bundles/router.umd.js',
'@angular/router/upgrade': 'npm:@angular/router/bundles/router-upgrade.umd.js',
'@angular/forms': 'npm:@angular/forms/bundles/forms.umd.js',
'@angular/upgrade': 'npm:@angular/upgrade/bundles/upgrade.umd.js',
'@angular/upgrade/static': 'npm:@angular/upgrade/bundles/upgrade-static.umd.js',
// other libraries
'ng2-translate': 'npm:ng2-translate/bundles',
'rxjs': 'npm:rxjs',
'underscore.string': 'npm:underscore.string/dist',
'angular-in-memory-web-api': 'npm:angular-in-memory-web-api/bundles/in-memory-web-api.umd.js'
},
Now there is no error reported inside the Chrome dev console , but there are issues that are not working:
- no http 404 so all js files are correctly download in the order expected (starting from index.html then all the .js refered by scripts tags then all the .js file refered by system.config.js)
- The 2 ways data binding is not working and we are forced to inject zone.js inside the component constructor and use it's run() method to force updates on UI
Other relevent sources are the component and the html
Component and it's template (as we type inside a field we expect the form.value | json to display 'live' the content of the input text)
import { Component, OnInit, NgZone } from '@angular/core';
import { Router } from '@angular/router';
import { AuthenticationService, ILoginAjaxResponse } from './service/authentication.service';
export class Credentials {
email: string;
password: string;
}
@Component({
selector: 'as-login',
templateUrl: 'app/login/login.component.html',
})
export class LoginComponent implements OnInit {
credentials = new Credentials();
constructor(
private authenticationService: AuthenticationService,
private router: Router,
private zone: NgZone) {
}
public ngOnInit() {
// Test A
// -------------------------------
// this is visible in UI text box
// this is visible in the UI {{credentials | json}} output
// this is NOT visible in the UI {{form.value | json}} output
this.credentials.email = 'john.doe@planet.com';
// Test B
// -------------------------------
// this is NOT visible in UI text box
// this is NOT visible in the UI {{credentials | json}} output
// this is NOT visible in the UI {{form.value | json}} output
setTimeout(() => {
this.credentials.email = '11111111@planet.com'
}, 3000);
// Test C
// -------------------------------
// this is visible in UI text box
// this is visible in the UI {{credentials | json}} output
// this is visible in the UI {{form.value | json}} output
setTimeout(() => {
this.zone.run(() => {
this.credentials.email = '22222222@planet.com'
});
}, 6000);
}
public onSubmit() {
this.authenticationService.login(this.credentials)
.subscribe((response) => this.handleResponse(response));
}
private handleResponse(response: ILoginAjaxResponse) {
this.router.navigateByUrl('spa/sync')
.catch((reason) => { console.log(reason); });
}
}
<p>Form:</p>
<pre>
{{ form.value | json }}
</pre>
<p>Model:</p>
<pre>
{{ credentials | json }}
</pre>
<form #form="ngForm" novalidate>
<input type="text" class="form-control"
name="email" [(ngModel)]="credentials.email">
<input type="password" class="form-control"
name="password" [(ngModel)]="credentials.password">
<input class="btn btn-lg btn-primary btn-block"
(click)="onSubmit()"
type="submit" value="Submit">
</form>