Angular 4 jquery doesn't work - javascript

I am trying to use jquery to my Angular 4 app.I had followed all the steps to install jquery on my Angular 4.However jquery still dont work.
I had put the jquery code on the component like this.
home.component.ts
import * as jQuery from 'jquery'
import { Component, OnInit } from '#angular/core';
#Component({
selector: 'app-home',
templateUrl: './home.component.html',
styleUrls: ['./home.component.css']
})
export class HomeComponent implements OnInit {
constructor(db: AngularFireDatabase,public authService: AuthService,public
afAuth: AngularFireAuth,) {
$(document).ready(function(){
$("#showAppinfo").click(function(){
$("#appinfo").slideToggle();
});
});
ngOnInit()
{}
}
And my Html is the following
home.component.html
<h1>This is Home page!!</h1>
<h2 id="showAppinfo">Basic App-info</h2>
<ul class="list-group" id="appinfo">
<li class="list-group-item">Publiser: {{ (appinfo | async)?.Publisher }}</li>
<li class="list-group-item">Publication_Year: {{ (appinfo | async)?.Publication_Year }}</li>
<li class="list-group-item">Version: {{ (appinfo | async)?.Version }}</li>
<li class="list-group-item">Registered Users: {{ (appinfo | async)?.Rusers }}</li>
<li class="list-group-item">Languages: {{ (appinfo | async)?.Language }}(Only)</li>
</ul>
But nothing happens when I click on <h2 id="showAppinfo">Basic App-info</h2>. Can you tell my if I am using the jquery code in the correct place?? The problem is on code or on the jquery instalation??

The basic problem is that you're trying to manipulate your template in the constructor. But when your component constructor executes, #showAppinfo and #appInfo elements don't exist yet because the view has not been built.
Operations that depend on view elements need to be performed at the earliest in the ngAfterViewInit lifecycle hook
export class HomeComponent implements OnInit, OnAfterViewInit
...
ngAfterViewInit(){
// do your template manipulation here
}
You can test this with something like console.log($("#showAppinfo")) and you'll see that it doesn't log any element constructor(), but it does in ngAfterViewInit()

Following the steps that works for me:
Install jquery
npm install jquery
Install ts type
npm install #types/jquery
Add jquery.min.js in your .angular-cli.json:
"scripts": [
"../node_modules/jquery/dist/jquery.min.js"
]
Create a service to JQuery with the Token, Provider and Factory:
import { InjectionToken } from '#angular/core';
import * as $ from 'jquery';
export const JQUERY_TOKEN = new InjectionToken<JQueryStatic>('jquery');
export function jQueryFactory() {
return $;
}
export const JQUERY_PROVIDER = { provide: JQUERY_TOKEN, useFactory: jQueryFactory };
Add the Provider in Module:
#NgModule({
declarations: [
...
],
providers: [
JQUERY_PROVIDER,
...
]
})
Use DI in any component:
constructor(
#Inject(JQUERY_TOKEN) private $: JQueryStatic
)
Be happy :D
this.$('body').css('background-color', 'red')

Easiest and Shortest way possible to use jQuery in Angular 2/4
1st Step
From index.html
my-test-project\src\index.html
Type jQuery cdn below app-root tag.
...
<body>
<app-root></app-root>
<script src="https://code.jquery.com/jquery-3.2.1.min.js"></script>
</body>
...
2nd Step
my-test-project\src\app\test\test.component.ts
Go to your desired components .ts script.
import { Component, OnInit } from '#angular/core';
// this line will allow you to use jQuery
declare var $: any;
#Component({
...
})
3rd Step
my-test-project\src\app\test\test.component.ts
Test jQuery by logging 'I<3Cats' inside jQuery syntax $(() => { /* content here */ }).
export class TestComponent implements OnInit {
constructor() { }
ngOnInit() {
$(() => {
console.log('hello there!');
});
}
}
You can also use this technique with other javscript libraries. I don't know if this is safe but will sure help you. quite

i had an issue with jquery not working on bootstrap navbar and solved like this...
import { Component, OnInit, AfterViewInit, ElementRef } from '#angular/core';
//declare var $: any; //old code..
#Component({
selector: 'app-navbar',
templateUrl: './navbar.component.html',
styleUrls: ['./navbar.component.scss']
})
export class NavbarComponent implements OnInit, AfterViewInit {
constructor(private elem: ElementRef) { }
ngOnInit() {
}
ngAfterViewInit() {
this.elem.nativeElement.querySelectorAll('.navbar-nav>li>a').forEach((el) => {
el.addEventListener('click', () => {
this.elem.nativeElement.querySelector('.navbar-toggler').classList.toggle('collapsed');
this.elem.nativeElement.querySelector('.navbar-collapse').classList.toggle('show');
});
})
//old code...
// $('.navbar-nav>li>a').on('click', function () {
// $('.navbar-collapse').collapse('hide');
// });
}
}

Not sure what slideToggle() is doing, but FYI in Angular if you added
#ref to h2..
you can then add
#ViewChild('ref')
h2El:Element;
in Typescript associated to the HTML.
to do equivalent of $("#showAppinfo")..
If you used this in the HTML
<h2 #ref (click)="handler()">...</h2>
you'd have click handler..
so in Typescript add
handler() {
this.h2El.slideToggle();
}

your onInit method was inside the constructor, try it in the following way
constructor(db: AngularFireDatabase, public authService: AuthService, public afAuth: AngularFireAuth) {
$(document).ready(function () {
$("#showAppinfo").click(function () {
$("#appinfo").slideToggle();
});
});
}
ngOnInit() { }}

Related

Load multiple scripts in Component

I am new to angular 6. I just start learning angular 6. While creating a project i am stuck into error.
I am simply adding external scripts into my component and getting error
Here is my code
import { Component, OnInit } from '#angular/core';
import * as $ from 'src/assets/js/jquery-3.2.1.min.js';
import 'src/assets/js/countdowntime.js';
#Component({
selector: 'app-comingsoon',
templateUrl: './comingsoon.component.html',
styleUrls: ['./comingsoon.component.css']
})
export class ComingsoonComponent implements OnInit {
constructor() { }
ngOnInit() {
console.log($) // here is am getting output
}
}
Error:
Uncaught ReferenceError: jQuery is not defined at Object..
/src/assets/js/countdowntime.js (countdowntime.js:92)
Update your code
Add jQuery to your index.html or angular.json file
import { Component, OnInit } from '#angular/core';
declare var jQuery:any;
#Component({
selector: 'app-comingsoon',
templateUrl: './comingsoon.component.html',
styleUrls: ['./comingsoon.component.css']
})
export class ComingsoonComponent implements OnInit {
constructor() {
// load countdown
var c = document.createElement("script");
c.type = "text/javascript";
c.src = "src/assets/js/countdowntime.js";
document.getElementsByTagName("head")[0].appendChild(c);
}
ngOnInit() {
console.log(jQuery) // here is am getting output
}
}
You should be able to add jquery as a package and reference it in your component code, so it can get picked up by Webpack:
$ npm add jquery
Then inside your TypeScript code:
import * as $ from 'jquery';
...
export class FooComponent implements OnInit {
ngOnInit() {
console.log($);
}
}
Solution 1 :
Use Jquery types
Need to add types for jquery version.
you can find jquery types here
https://www.npmjs.com/package/#types/jquery
As typescript is strongly typed
For all items which we use in a component should have types
Solution 2 :
create a variable $ and assign its type to any
A workaround if you're not able to find type for the current jquery version which is
declare var $: any;
#Component({
selector: 'app-comingsoon',
templateUrl: './comingsoon.component.html',
styleUrls: ['./comingsoon.component.css']
})
inside your component life cycle check the value of the dollar, you will find jquery properties and method. Your error will be resolved
ngOnInit() {
console.log($)
}

Using external js to sort tables in Angular2

I have a problem. Im creating an app in Angular2 using Semantic UI. In the documentation said that you can create a sortable table. it say that you have to import a tablesort.js and call $('table').tablesort() when the DOM is ready.
My problem start when it doesnt recognize that .tablesort is a method. It say that its not a method from Jquery so i dont know how to do work correctly
Here is my code:
import { Component, OnInit } from '#angular/core';
import { UserService } from "services/user.service";
import { Bet } from "models/bet";
import * as $ from 'jquery';
#Component({
selector: 'history',
templateUrl: 'history.component.html',
styleUrls: ['./history.component.css'],
})
export class HistoryComponent implements OnInit {
url: string;
bets = [];
constructor(private userService: UserService) {
this.url = 'http://localhost:3000/bets/history';
}
ngOnInit(): void {
this.userService.getHistory(this.url).subscribe(this.sucess.bind(this), this.error);
$('table').tablesort();
}
}
And in my index im importing:
<script type="text/javascript" src="semantic/components/tablesort.js"></script>
How can i do that Jquery recognize a external JS and can use the function from that JS.

Create a Dynamic Component in Angular 2

Hey I am new to angular 2, I have played with angular 2 for the past week and wondered if it possible to generate a dynamic component with a dynamic template and dynamic styles. This means that the follwoing should be like this
#Component({
// 2a
selector: 'dynamic placeholder',
// 2b
styles: [`dynamic styles`]
// 2c
template: `dynmic template`
})
is it possible to do it in angular 2, I remember that such this is maybe possible in angular 1.
Any Help will be appreciated(Escpecially plunkers with simple code)
This is what I have achieved so far: try using ComponentFactoryResolver:
#NgModule({
imports: [BrowserModule],
declarations: [AppComponent],
bootstrap: [AppComponent]
})
export class AppModule {
}
#Component({
selector: 'my-app',
template: `
<div>Hello, world!</div>
`
})
export class AppComponent {
}
#NgModule({
declarations: [HomeComponent],
exports: [HomeComponent]
})
export class HomeModule {
}
#Component({
selector: 'home',
template: `
<div>This is home</div>
`
})
export class HomeComponent {
}
#Component({
selector: 'hello-world',
template: `
<div>
Hello, world!, {{name}}
The answer is: {{getAnswer()}}
</div>
`
})
export class HelloWorldComponent implements AfterViewInit {
private name:string = 'You';
constructor(private helloWorldService: HelloWorldService) {
}
ngAfterViewInit(): void {
this.name = 'Me';
}
private getAnswer() {
return this.helloWorldService.giveMeTheAnswer();
}
}
#NgModule({
declarations: [HomeComponent, HelloWorldComponent],
providers: [HelloWorldService],
exports: [HomeComponent]
})
export class HomeModule {
}
#Component({
selector: 'home',
template: `
<button (click)="sayHello()">Say hello</button>
<div>This is home</div>
`
})
export class HomeComponent {
constructor(private componentFactoryResolver: ComponentFactoryResolver,
private viewContainerRef: ViewContainerRef) {
}
private sayHello() {
const factory = this.componentFactoryResolver.resolveComponentFactory(HelloWorldComponent);
const ref = this.viewContainerRef.createComponent(factory);
ref.changeDetectorRef.detectChanges();
}
}
Here is a plunker which enables to created dynamic component, I don't know if creating dynamic css is possible,I would be pleased if some can I answer my question:
http://plnkr.co/edit/ZXsIWykqKZi5r75VMtw2?p=preview
With TypeScript and latest version of Angular2 (I believe that feature has been released in 2.4.0) you can create 1 base component and then extend it. All decorators/annotations on properties (#Input/#Output/#ViewChild) will be copied. However, you must specify for each ancestor #Component properties, i.e. you cannot overwrite only selector, but everything. That is RIGHT approach.
Another approach -> use reflect-metadata to update decorators on Component classes (probably that is what you are looking for, as it that case you can overwrite 1 property at time), but be careful to export (i.e. make public) all Components/Directives/Services that are used inside of Component that you want to overwrite. For example, some libraries have multiple Components, and some of them are supposed to be used only internally (i.e. there is no way to import it into your module in normal way... however, you can try providers). If you try to "overwrite", say, css with reflect-metadata and it uses internal components -> angular/typescript will crash, as it cannot resolve "internal" stuff. You can start with this answer: StackOverflow

Semantic UI with Angular2 - How to set Sidebar settings from jQuery in a component?

I have an Angular2 application and I want to use Semantic UI. However, there are some jQuery configurations like below that I have to run after a component loaded:
$('#app .ui.sidebar')
.sidebar({context:$('#app')})
.sidebar('setting', 'transition', 'overlay')
It is not working by importing the js file in the head of index.html or writing it in a <script> tag inside of a component template. Is there a "typescript way" to do that or how can I use a js file inside of a component?
I found this link about using jQuery in directives, then I created a sidebar directive:
import {Directive, ElementRef, OnDestroy, OnInit, Input} from '#angular/core';
import {HostListener} from "#angular/core/src/metadata/directives";
declare var $: any
#Directive({
selector: '.ui.sidebar'
})
export class SidebarDirective implements OnInit, OnDestroy {
#Input() context: string;
constructor(private el: ElementRef) {
}
public ngOnInit() {
$(this.el.nativeElement)
.sidebar({context: this.context})
.sidebar('setting', 'transition', 'overlay');
}
public ngOnDestroy() {
}
}
Then, I used it in the template:
<div id="app">
<div context="#app" class="ui left vertical menu sidebar"></div>
<div class="pusher"></div>
</div>
I have spent quite some time to get this working although it is rather simple in the end. Hope to save you some time ...
There is no need to create a directive, you can use the jQuery command as you would use with JavaScript (described at https://semantic-ui.com/modules/sidebar.html#/usage). However, "$" has to be declared and the command has to be located in a TypeScript function ("toggle()"):
import {Component} from '#angular/core';
declare var $: any;
#Component({
selector: 'app-root',
templateUrl: './app.component.html'
})
export class AppComponent {
toggle() {
$('.ui.sidebar').sidebar('toggle');
}
}
The corresponding section of the template may look like this:
<div class="ui fixed inverted main menu">
<a (click)="toggle()" class="launch icon item">
<i class="content icon"></i>
<p style="padding-left:1em">Menu</p>
</a>
</div>
Don't forget to add jQuery to the scripts section of .angular-cli.json:
"scripts": [
"../node_modules/jquery/dist/jquery.js",
"../node_modules/semantic-ui-css/semantic.min.js"
],
I'm using Semantic UI 2.2.12 which already depends on jQuery 3.2.1. Angular version is 4.4.4 running on node.js 6.11.2.
import { Component, OnInit } from '#angular/core';
declare var $:any;
#Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent implements OnInit {
title = 'app works!';
ngOnInit(){
$('#app .ui.sidebar')
.sidebar({context:$('#app')})
.sidebar('setting', 'transition', 'overlay') ;
}
}

Load dynamic component created on the fly in angular2 final

Previously with DynamicComponentLoader I was able to write like this:
import {Directive, Component, ViewContainerRef, DynamicComponentLoader} from '#angular/core';
#Directive({
selector: '[some-directive]'
})
export class SomeDirective {
costructor(dcl: DynamicComponentLoader, viewContainerRef: ViewContainerRef) {
// fetch template from the server
fetch(...).then((template) => {
#Component({
selector: 'div[some-relatively-unique-attribute-name]',
template: template
})
class AdHocComponent {}
dcl.loadNextToLocation(AdHocComponent, viewContainerRef).then(() => {
console.log('success');
});
});
}
}
Now with angular2 final and NgModules I see examples like this: http://plnkr.co/edit/P0spNzu8JbQad2aKACsX?p=info
(Discussed here https://github.com/angular/angular/issues/10735)
To dynamically load a HelloComponent but it requires the HelloComponent to be declared up front when the root NgModule is being created.
How can I load an ad-hoc created component into my view?
I found this: http://plnkr.co/edit/wh4VJG?p=preview
But it is an insane amount of code to achieve a simple task like that.
This might be that what you're looking for:
export class App {
#ViewChild('placeholder', {read: ViewContainerRef}) viewContainerRef;
constructor(private compiler: Compiler) {}
addItem () {
#NgModule({declarations: [HelloComponent]})
class DynamicModule {}
this.compiler.compileModuleAndAllComponentsAsync(DynamicModule)
.then(({moduleFactory, componentFactories}) => {
const compFactory = componentFactories
.find(x => x.componentType === HelloComponent);
const cmpRef = this.viewContainerRef.createComponent(compFactory, 0);
});
}
}
See also live Plunker
Related question:
Angular2 RC6 - Dynamically load component from module

Categories

Resources