Migrating Web App to Angular 2 - javascript

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

Related

(Angular 2/4/5/6) Adding tawk widget to specific pages in Angular 6

Solution:
I got my solution here How to load external scripts dynamically in Angular?
And I checked for my path in app component to load the script accordingly.
import { Component, OnInit } from "#angular/core";
import { NavigationStart, Router } from "#angular/router";
import { Subscription } from "rxjs";
import { ScriptService } from "./shared/script.service";
import { Location } from "#angular/common";
#Component({
selector: "app-root",
templateUrl: "./app.component.html",
styleUrls: ["./app.component.scss"],
})
export class AppComponent implements OnInit {
constructor(
router: Router,
private location: Location,
public script: ScriptService,
) {}
ngOnInit() {
if (!this.location.path().includes("admin")) {
// load script for tawk widget
this.script.load("tawk").catch(error => console.log(error));
}
}
}
Previous Question:
I have difficulties adding the tawk widget to specific components in the angular 6 project. If I add it to index.html page below app-root, it shows up in all pages of the project. Is there any other way of doing it?
Sample code:
<!--Start of Tawk.to Script-->
<script type="text/javascript">
var Tawk_API=Tawk_API||{}, Tawk_LoadStart=new Date();
(function(){
var s1=document.createElement("script"),s0=document.getElementsByTagName("script")[0];
s1.async=true;
s1.src='https://embed.tawk.to/17f35g40afc2c34e96e75909/default';
s1.charset='UTF-8';
s1.setAttribute('crossorigin','*');
s0.parentNode.insertBefore(s1,s0);
})();
</script>
<!--End of Tawk.to Script-->
Sample code taken from here --->
Integrating tawk.to into Angular 6 (Angular 2) app
I've tried the following site,
Adding JavaScript File to Angular 4 Component but it still shows up for every page. Appreciate your help!
the easiest way would be to create a component, and than inside your component's .ts, to append script to the body like so:
onInit(): void {
const s = this._renderer.createElement('script');
s.text = `var Tawk_API = Tawk_API || {}, Tawk_LoadStart = new Date();
(function () {
var s1 = document.createElement("script"), s0 = document.getElementsByTagName("script")[0];
s1.async = true;
s1.src = 'https://embed.tawk.to/${id}/default';
s1.charset = 'UTF-8';
s1.setAttribute('crossorigin', '${cors}');
s0.parentNode.insertBefore(s1, s0);
})();
this._renderer.appendChild(this._document.body, s);
}
Of course you'll need to inject Document and renderer into constructor
constructor(
private _renderer: Renderer2,
#Inject(DOCUMENT) private _document,
) {}
and make sure you set your twalk.to id and cors (${id}, ${cors})

my javascript function does not load on initial page load

I'm building an app with an Angular2 frontend and a web API backend using the asp.net Angular2 template. I have an inline script in my index.html file that does not get loaded on the initial page load, but when i refresh the page it gets loaded. Below is the code.
<script>
$(function () {
$('.toggle-nav').click(
function () {
$('#body-holder').toggleClass('show-nav');
return false;
});
});
</script>
I tried loading it in my component.ts file within the ngOnInit function but i get a cannot find $ error when i try that.
import { Component, OnInit } from '#angular/core';
declare var $:any; // this is required
#Component({
selector: 'app-root',
template: `Something`
})
export class AppComponent implements OnInit {
ngOnInit() {
$('.toggle-nav').click(function () {
$('#body-holder').toggleClass('show-nav');
});
}
}

Angular 2 component directive not working

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

Angular2 Component communication in JS

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.

Angular2, view not updating after variable changes in settimeout

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);
}
}

Categories