I am trying to setup my first angular2 application as an experiment and am using the latest beta release.
I am facing a weird issue where the variable i am using in my view is not being updated after setting a timeout.
#Component({
selector: "my-app",
bindings: []
})
#View({
templateUrl: "templates/main.component.html",
styleUrls: ['styles/out/components/main.component.css']
})
export class MainComponent {
public test2 = "initial text";
constructor() {
setTimeout(() => {
this.test2 = "updated text";
}, 500);
}
}
As you can see i have a variable named test2 and in the constructor i set a timeout of 500 ms where i am updating the value to "updated text".
Then in my view main.component.html i simply use:
{{ test2 }}
But the value will never be set to "updated text" and stays on "initial text" forever even though the update part is being hit. If i follow the angular2 tutorial they dont really give me an answer to this solution. Was wondering if anyone would have an idea of what i am missing here.
edit: my full code i am using including the bootstrap and html etc
<html>
<head>
<title>Angular 2</title>
<script src="/node_modules/systemjs/dist/system.src.js"></script>
<script src="/node_modules/reflect-metadata/reflect.js"></script>
<script src="/node_modules/angular2/bundles/angular2.dev.js"></script>
<script src="/node_modules/q/q.js"></script>
<script src="/node_modules/jquery/dist/jquery.js"></script>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<script src="/bower_components/breeze-client/breeze.debug.js"></script>
<script src="/bower_components/datajs/datajs.js"></script>
<script src="/bower_components/bootstrap-less/js/collapse.js"></script>
<script src="/bower_components/bootstrap-less/js/modal.js"></script>
<script src="/bower_components/signalr/jquery.signalR.js"></script>
<script src="http://localhost:64371/signalr/js"></script>
<link href="styles/out/main.css" type="text/css" rel="stylesheet" />
<script>
System.config({
map: {
rxjs: '/node_modules/rxjs' // added this map section
},
packages: {'scripts/out': {defaultExtension: 'js'}, 'rxjs': {defaultExtension: 'js'}}
});
System.import('scripts/out/main');
</script>
</head>
<body>
<my-app>loading...</my-app>
</body>
</html>
main.ts with the bootstrap:
import {Component} from 'angular2/core';
import {bootstrap} from 'angular2/platform/browser'
import {COMMON_DIRECTIVES} from './constants';
import {MainComponent} from './components/main.component'
bootstrap(MainComponent);
main-component.html
{{ test2 }}
As Vlado said, it should work ;-)
I think that the angular2-polyfills.js library should be included into your page. I can't see it. This file is essentially a mashup of zone.js and reflect-metadata. Zones take part of the detection of updates.
You could have a look at this video where Bryan Ford explains what it is: https://www.youtube.com/watch?v=3IqtmUscE_U.
Hope it helps you,
Thierry
That should work. Do you have any other errors in console?
#Component({
selector: 'my-app',
template: `<h1>Hello {{title}}</h1>`
})
export class App {
public title: string = "World";
constructor() {
setTimeout(() => {
this.title = "Brave New World"
}, 1000);)
}
}
Look at this Plunker:
http://plnkr.co/edit/XaL4GoqFd9aisOYIhuXq?p=preview
I had a very similar problem to the OP where even in a basic Angular2 setup changes to bound properties would not be reflected by the view automatically. At this point in time we're using Angular2 2.0.0-rc.6.
There was no error message.
In the end I found the culprit to be a reference to es6-promise.js, which was 'required' by a third party component we use. Somehow this interfered with the core-js reference we are using which is suggested with rc6 in some of the Angular2 tutorials.
As soon as I got rid of the es6-promise.js reference, the view updated correctly after changing a property on my component (via Promise or timeout).
Hope this helps somebody some day.
In Angular2 (~2.1.2) another way to make it work is through the ChangeDetectorRef class. The original question code would look like this:
import {
ChangeDetectorRef
// ... other imports here
} from '#angular/core';
#Component({
selector: "my-app",
bindings: []
})
#View({
templateUrl: "templates/main.component.html",
styleUrls: ['styles/out/components/main.component.css']
})
export class MainComponent {
public test2 = "initial text";
constructor(private cd: ChangeDetectorRef) {
setTimeout(() => {
this.test2 = "updated text";
// as stated by the angular team: the following is required, otherwise the view will not be updated
this.cd.markForCheck();
}, 500);
}
}
Related
I'm new to Angular.
I'm trying to use xterm.js (https://xtermjs.org/) but it display badly.
Here is the render :
Render
I created a xterm component. The xterm.component.ts file code is :
import { Component, OnInit } from '#angular/core';
import { Terminal } from "xterm";
#Component({
selector: 'app-xterm',
templateUrl: './xterm.component.html',
styleUrls: ['./xterm.component.css'],
})
export class XtermComponent implements OnInit {
public term: Terminal;
container: HTMLElement;
constructor() { }
ngOnInit() {
this.term = new Terminal();
this.container = document.getElementById('terminal');
this.term.open(this.container);
this.term.writeln('Welcome to xterm.js');
}
}
My xterm.component.html only contains this :
<div id="terminal"></div>
I don't really know what to do more ...
Thanks in advance guys
You must set the component encapsulation
#Component({
encapsulation: ViewEncapsulation.None,
...
})
Encountered the same problem and found this page.
Maybe this is too late for the OP, but could be useful for others.
The styles are wrong because 1) the xterm.css is not loaded, and 2) the encapsulation.
My solution to 1) was to add #import 'xterm/dist/xterm.css'; in the scss file for this component.
And 2) can be solved by setting encapsulation: ViewEncapsulation.None as Victor96's answer, or better setting encapsulation: ViewEncapsulation.ShadowDom.
Hope this helps.
I know this is old, but I had to put terminal initialation in ngAfterViewInit. Otherwise the DOM elements are undefined.
Try to use in template reference variable by using the hash symbol
<div #myTerminal></div>
and in component
#ViewChild('myTerminal') terminalDiv: ElementRef;
In ngOnInit
ngOnInit() {
this.term = new Terminal();
this.term.open(this.terminalDiv.nativeElement);
this.term.writeln('Welcome to xterm.js');
}
I am trying to move a web app to Angular2. I had successfully moved HTML & CSS to angular's component.html & component.css respectively. However, I am having trouble with .js files.
How do I incorporate .js file into component.ts?
.js file:
A = (function(w){
var init = function(){};
var scrollToElement = function(){};
}(window);
$(document).ready(function() {
A.init();
A.scrollToElement();
....
});
component.ts
import { Component, OnInit } from '#angular/core';
declare var $: any;
#Component({
selector: 'app-home',
templateUrl: './home.component.html',
styleUrls: ['./home.component.css']
})
export class HomeComponent implements OnInit {
constructor() { }
ngOnInit() {
$.getScript('assets/js/script.js');
}
}
Is this correct? What am I doing wrong?
It's better if you write js code in TypeScript in component.ts
and there is no need of jQuery's document.ready, window.load etc functions
because angular have its own life cycle hooks
see this --> See This
Using feedback by #SreedevR & #mlMughal, here's how i did it.
In index.html, I include the script file:
<!doctype html>
<html lang="en" class="no-js">
<head>
<base href="/">
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<script src="assets/js/script.js"></script>
</head>
<body></body>
</html>
In component.ts:
export class HomeComponent implements OnInit {
A:any;
constructor() { }
ngOnInit() {}
ngAfterViewInit(){
A.init();
A.scrollToElement();
}
}
}
Please include the js in your main html file and you can call the fiction in the component.
Eg: If you script file is test.js please include that in the html file and call any function declared in it in the component like
f(){
new test();
}
Hope this is clear now
I am a beginner in angular 2 and I want to make my first app working. I am using TypeScript.
I have the app.component.ts in which I have made a directive to another compoent called todos.component but I am getting the following error at compile time:
[0] app/app.component.ts(7,3): error TS2345: Argument of type '{ moduleId: string; selector: string; directives: typeof TodosComponent[]; templateUrl: string; s ...' is not assignable to parameter of type 'Component'.
[0] Object literal may only specify known properties, and 'directives' does not exist in type 'Component'.
My code is like this:
index.html
<html>
<head>
<title>Angular 2 QuickStart</title>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="styles.css">
<!-- 1. Load libraries -->
<!-- Polyfill(s) for older browsers -->
<script src="node_modules/core-js/client/shim.min.js"></script>
<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>
</head>
<!-- 3. Display the application -->
<body>
<app-root>Loading...</app-root>
</body>
</html>
app.component.ts
import { Component } from '#angular/core';
import {TodosComponent} from './todos/todos.component';
#Component({
moduleId : module.id,
selector: 'app-root',
directives: [TodosComponent],
templateUrl : 'app.component.html',
styleUrls : ['app.component.css']
})
export class AppComponent {
title: string = "Does it work?";
}
app.component.html:
<h1> Angular 2 application</h1>
{{title}}
<app-todos></app-todos>
todos.component.ts
import { Component, OnInit } from '#angular/core';
#Component({
moduleId : module.id,
selector: 'app-todos',
template: '<h2>Todo List</h2>'
})
export class TodosComponent {
title: string = "You have to do the following today:";
}
Without the directive, the app works fine.
Any help would be appreciated!
Thanks in advance!
In your app.component.ts you define directive: [TodosComponent].
The directive property has been removed in RC6 from the #Component() decorator.
The solution to this, is to:
create an NgModule and
declare the TodosComponent inside the declarations: [] array.
See here for an example of AppModule:
https://angular.io/docs/ts/latest/tutorial/toh-pt3.html
module.id was added in intially when angular2 was at beta version.Since with new version and angular cli support it is not required to add moduleId:module.id,you can remove from .ts files
I am unable to communicate between two component in Angular 2 using JS. This is link for tutorial.
I think I am missing something with directives.
I tried to change it with declarations as well
This is app.main.js
(function () {
var Component = ng.core.Component
var bootstrap = ng.platformBrowserDynamic.bootstrap
var RandomComponent = Component({
selector: 'random-component',
template: `
<h2> Hsdsdffdsdfi <h2>
`
}).Class({
constructor: function() {
//empty
}
});
var AppComponent = Component({
selector: 'main-app',
directives: [RandomComponent],
template: `
<h1> Hi {{username}}<h1>
<random-component></random-component>
`
}).Class({
constructor: function() {
//empty
this.username = "Username"
}
});
document.addEventListener('DOMContentLoaded', function(){
bootstrap(AppComponent);
});
})();
and this is index.html
<html>
<head>
<title>Angular 2 QuickStart JS</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="styles.css">
<!-- 1. Load libraries -->
<!-- IE required polyfill -->
<script src="node_modules/core-js/client/shim.min.js"></script>
<script src="node_modules/zone.js/dist/zone.js"></script>
<script src="node_modules/reflect-metadata/Reflect.js"></script>
<script src="node_modules/rxjs/bundles/Rx.umd.js"></script>
<script src="node_modules/#angular/core/bundles/core.umd.js"></script>
<script src="node_modules/#angular/common/bundles/common.umd.js"></script>
<script src="node_modules/#angular/compiler/bundles/compiler.umd.js"></script>
<script src="node_modules/#angular/platform-browser/bundles/platform-browser.umd.js"></script>
<script src="node_modules/#angular/platform-browser-dynamic/bundles/platform-browser-dynamic.umd.js"></script>
<!-- 2. Load our 'modules' -->
<script src='app/app.main.js'></script>
</head>
<!-- 3. Display the application -->
<body>
<main-app>Loading....</main-app>
</body>
</html>
I am currently using Angular 2 RC5, and do not wish to go to ts. I also could not find any documentation regarding JS as well. If anyone knows a good documentation link for 'JS' (not ts), please help with that as well.
NgModules
Angular2 RC5 introduced NgModules. According to the documentation,
Angular Modules help organize an application into cohesive blocks of functionality.
You need to define at least one module in your Angular application. You also should bootstrap that (root/main) module instead of a component (AppComponent in your case).
Another change is the way you declare your components and directives. Instead of using the directives property in every component, now you list them in the module using the declarations property.
Here's the working solution:
(function () {
var Component = ng.core.Component
var NgModule = ng.core.NgModule;
var BrowserModule = ng.platformBrowser.BrowserModule;
var bootstrap = ng.platformBrowserDynamic;
var AppComponent = Component({
selector: 'main-app',
template: `
<h1>Hi {{username}}</h1>
<random-component></random-component>
`
}).Class({
constructor: function() {
this.username = 'Username';
}
});
var RandomComponent = Component({
selector: 'random-component',
template: `
<h2>Random title<h2>
`
}).Class({
constructor: function() { }
});
AppModule = NgModule({
imports: [
BrowserModule
],
declarations: [
RandomComponent,
AppComponent
],
bootstrap: [
AppComponent
]})
.Class({
constructor: function() { }
});
document.addEventListener('DOMContentLoaded', function() {
bootstrap.platformBrowserDynamic()
.bootstrapModule(AppModule);
});
})();
Tutorials
Unfortunately, the Angular 2.0 docs about Javascript are definitely not as rich as the docs about Typescript. You can check the QuickStart Guide (there's and appendix regarding NgModule) or the corresponding Typescript chapter.
I'm trying to get a very basic, functional structure set up for Angular 2. It will have only the most basic API elements so that as the framework advances, I can advance my structure.
Currently, I'm at my wit's end as to how to perform the simple act of passing services. Here is some example source, taken right from the comments of the most recent DefinitelyTyped file:
class Greeter {
greet(name: string) {
return 'Hello ' + name + '!';
}
}
#Component({
selector: 'greet',
appInjector: [Greeter]
})
#View({
template: `{{greeter.greet('world')}}!`
})
class HelloWorld {
greeter: Greeter;
constructor(greeter: Greeter) {
this.greeter = greeter;
}
}
bootstrap(HelloWorld);
As you can see, I'm using Typescript 1.5 in this example.
I have tried to inject the Greeting service in the Component annotation using hostInjector, injectibles and appInjector. I've also tried adding it to the second argument of the bootstrap call, as in bootstrap(HelloWorld, [Greeter]).
In all cases I get this error message when trying to run it in the browser:
Error during instantiation of Token(ComponentRef)!. ORIGINAL ERROR: Cannot resolve all parameters for HelloWorld(?). Make sure they all have valid type or annotations.
Of course, if I remove greeter: Greeter argument from the constructor, the error in question goes away and is replaced by other, expected errors further down the chain.
Ideas?
EDIT
I updated the title of this question to specify that I am using TypeScript 1.5
I had a similar problem when using typescript 1.5.0-beta and angular 2.0.0-alpha.28 (not sure if the versions are strictly relevant) with gulp.
You need to tell the typescript compiler to export metadata so the DI injector knows what to do. I did this by adding emitDecoratorMetadata and experimentalDecorators to my tsconfig.json:
{
"compilerOptions": {
"module": "commonjs",
"emitDecoratorMetadata": true,
"experimentalDecorators": true,
"sourceMap": true,
"target": "es5"
}
}
After that you can add appInjector: [Greeter] to your #Component declaration like you've done or to the bootstrap declaration:
bootstrap(HelloWorld, [Greeter]);
Regarding TS2348. I got the same error. Got rid of ComponentAnnotaion and ViewAnnotation and this helped:
import {
bootstrap,
Component,
View
} from 'angular2/angular2';
I hope your code will work fine in typescript 1.5 release. Right now, you should use Inject annotation in typescript 1.5.0-beta.
import {
ComponentAnnotation as Component,
ViewAnnotation as View, bootstrap,
Inject
} from 'angular2/angular2';
#Component({
selector: 'app',
hostInjector: [Service]
})
#View({
template: '{{greeting}} world!'
})
class App {
constructor(#Inject(Service)service: Service) {
this.greeting = service.greeting();
setTimeout(() => this.greeting = 'Howdy,', 1000);
}
}
class Service {
greeting() {
return 'Hello';
}
}
bootstrap(App);
More a workaround than a solution, but if you move your service definition to a separate file (greeting.ts), and import it
import {Greeting} from 'greeting';
then the injector works correctly. This is built using tsc from the command line (taken from the 5 min quickstart on angular.io)
tsc --watch -m commonjs -t es5 --emitDecoratorMetadata app.ts
With angular2.0.0-alpha.32 I accomplished this with
/// <reference path="../../typings/angular2/angular2.d.ts" />
import {Component, View, bootstrap, NgFor} from 'angular2/angular2';
import {MyService} from 'js/services/MyService';
// Annotation section
#Component({
selector: 'my-app',
viewInjector: [MyService]
})
#View({
templateUrl: 'templates/my-app.tpl.html',
directives: [NgFor]
})
class MyComponent {
mySvc:MyService;
constructor(mySvc:MyService) {
this.mySvc = mySvc;
}
onInit() {
this.mySvc.getData();
}
}
bootstrap(MyComponent, [MyService]);
Here is the code, straight out of the plnkr.co template for injecting a service http://plnkr.co/edit/m5sHWWFmgYPrfsMv0u2r
import {
ComponentAnnotation as Component,
ViewAnnotation as View, bootstrap
} from 'angular2/angular2';
#Component({
selector: 'app',
viewInjector: [Service]
})
#View({
template: '{{greeting}} world!'
})
class App {
constructor(service: Service) {
this.greeting = service.greeting();
setTimeout(() => this.greeting = 'Howdy,', 1000);
}
}
class Service {
greeting() {
return 'Hello';
}
}
bootstrap(App);