Use external lib with Angular - javascript

I want to use this lib in my app : https://www.npmjs.com/package/jquery-animated-headlines
But i don't know how to import it.
First, i add these lines in my angular-cli.json
"styles": [
...
"../node_modules/jquery-animated-headlines/dist/css/jquery.animatedheadline.css"
],
"scripts": [
...
"../node_modules/jquery-animated-headlines/dist/js/jquery.animatedheadline.min.js"
]
Second, i install jquery npm install jquery --save
Then, i import jquery : import * as $ from 'jquery';
Finally i copy/paste their example :
TS :
constructor () {
$(function() {
$('.selector').animatedHeadline();
})
}
HTML :
<div class="selector">
<h1 class="ah-headline">
<span>My favorite food is</span>
<span class="ah-words-wrapper">
<b class="is-visible">pizza</b>
<b>sushi</b>
<b>steak</b>
</span>
</h1>
</div>
I get this error : Uncaught TypeError: $(...).animatedHeadline is not a function
I don't know what i'm doing wrong ...
Thanks

You don't need to include your libs in angular.json. Import it just where u need it.
First, install the packages:
npm install jquery jquery-animated-headlines --save
Then, go to the desired component and import them:
import * as $ from 'jquery' // in case u haven't imported it globally.
import * as animatedHeadline from 'jquery-animated-headlines;
#Component()
...
constructor () {
$(document).ready(() => $('.selector').animatedHeadline())
}

Here is how I got it to work, but there must be a better way. I created a new project using #angular/cli version6.
npm install --save jquery jquery-animated-headlines
In the angular.json file, add "node_modules/jquery-animated-headlines/dist/css/jquery.animatedheadline.css" to the styles array.
Update the app.component.html to:
<h2 #foo>Here are some links to help you start: </h2>
app.component.ts
import { Component, AfterContentInit, ViewChild, ElementRef } from '#angular/core';
import * as jQuery from 'jquery';
import 'jquery-animated-headlines';
#Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent implements AfterContentInit {
#ViewChild('foo') fooElement: ElementRef<any>;
ngAfterContentInit(): void {
$(this.fooElement.nativeElement).animatedHeadline();
}
}
Now things should work at this point, but don't seem to due to the way that the plugin library is written. I also had to go into the node_modules/jquery-animated-headlines/dist/js/jquery.animatedhealdine.js file and update the way that it is importing jquery.
The file comes looking like:
(function($) {
.
.
.
}(jQuery));
and I had to update it to:
(function (factory) {
"use strict";
if (typeof define === 'function' && define.amd) {
define(['jquery'], factory);
}
else if(typeof module !== 'undefined' && module.exports) {
module.exports = factory(require('jquery'));
}
else {
factory(jQuery);
}
}(function ($, undefined) {
.
.
.
}));
I'm not sure if there is a better way to handle this in Angular and this won't work well with an automated build system, but for local development it should work fine.
UPDATE
The way to get this working in your application is as follows.
In the angular.json file add:
"node_modules/jquery/dist/jquery.js",
"node_modules/jquery-animated-headlines/dist/js/jquery.animatedheadline.js"
to the scripts property.
In your component, use declare var $: any;. For example:
import { Component, AfterContentInit, ViewChild, ElementRef } from '#angular/core';
declare var $: any;
#Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent implements AfterContentInit {
#ViewChild('foo') fooElement: ElementRef<any>;
ngAfterContentInit(): void {
$(this.fooElement.nativeElement).animatedHeadline();
}
}
GitHub repo.

Related

Angular - How to import Javascript into Angular Component

In my Angular-11, I have this Javascript file:
"node_modules/admin-lte/plugins/bs-stepper/js/bs-stepper.min.js",
I added it to angular.json as shown above.
import Stepper from '...';
#Component({
selector: 'app-profile',
templateUrl: './profile.component.html',
styleUrls: ['./profile.component.css']
})
export class ProfileComponent implements OnInit {
name = 'Angular';
private stepper: Stepper;
next() {
this.stepper.next();
}
onSubmit() {
return false;
}
ngOnInit() {
this.stepper = new Stepper(document.querySelector('#stepper1'), {
linear: false,
animation: true
})
}
}
How do I import it into this component: profile.component.ts this way,
import Stepper from '...';
from the Javascript path
Thanks
You must first declare it in typing.d.ts and include angular.json script.
in angular.json
{
"build" : {
"scripts" : [
"node_modules/admin-lte/plugins/bs-stepper/js/bs-stepper.min.js",
....
]
in typing.d.ts
declare module 'admin-lte/plugins/bs-stepper/js/bs-stepper.min';
Note : If this is a JQuery package then you need to create an interface.
declare module 'jquery';
interface JQuery {
Stepper(DOM : any, options?: any): any;
}
finally you can now call it in the component.
in component
import Stepper from 'admin-lte/plugins/bs-stepper/js/bs-stepper.min';
Edit : Create a file named typing.d.ts inside the src folder. then add
/// <reference path = "typings.d.ts" />
to the top of the src/main.ts file
As it happens there is a NPM package for bs-stepper that could be used out-of-the-box with Angular.
1. Install the package
From the project root folder, run the command
npm install bs-stepper --save
Also install bootstrap if needed
npm install bootstrap --save
2. Import the CSS
styles.css
#import '~bs-stepper/dist/css/bs-stepper.min.css';
/* Also import bootstrap if needed */
#import '~bs-stepper/dist/css/bs-stepper.min.css';
3. Use ViewChild instead of querySelector
Using document.querySelector in an Angular app would search the entire DOM whereas the element would only be present in the current component. Based on the size of the app it might incur a performance issue. Instead you could use the #ViewChild decorator with with a template reference variable
Template (*.html)
<!-- Here, `bsStepper` is the template reference variable -->
<div #bsStepper id="stepper1" class="bs-stepper">
...
</div>
Component (*.ts)
import { Component, AfterViewInit, ViewChild, ElementRef } from '#angular/core';
import Stepper from 'bs-stepper';
#Component({
selector: 'my-app',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent implements AfterViewInit {
#ViewChild('bsStepper', { static: false }) stepperElement!: ElementRef<any>;
public stepper!: Stepper;
next() {
this.stepper.next();
}
onSubmit() {
return false;
}
ngAfterViewInit() {
this.stepper = new Stepper(this.stepperElement.nativeElement, {
linear: false,
animation: true
});
}
}
Working example: Stackblitz

Angular 7 add Javascript plugin

My intention is to add a javascript plugin, namely this one:
https://steven.codes/typerjs/
So far, my approach was to add its JS file in my assets folder and added the path to angular.json.
"scripts": [
"node_modules/jquery/dist/jquery.min.js",
"src/assets/js/typer.js"
]
My next step was to declare a var in the component and to try to call it in ngOnInit().
import {Component, OnInit} from '#angular/core';
import * as AOS from 'aos';
declare var Typer: any;
#Component({
selector: 'app-background',
templateUrl: './background.component.html',
styleUrls: ['./background.component.scss']
})
export class BackgroundComponent implements OnInit {
rotate = false;
constructor() { }
ngOnInit() {
this.rotate = !this.rotate;
AOS.init();
Typer.init();
}
}
I don't get any errors, but it's not working. Does somebody know a working approach?
There are multiple options that may help.
First - Node style require:
var typer = require("typer");
Second one use it like you already did with aos:
import * as typer from 'typer';
In this case you must be sure that your .js lib can be found. You have added it to angular.js so that should works.
In both cases the initialization should be the same:
ngOnInit() {
this.rotate = !this.rotate;
AOS.init();
typer.init();
}

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($)
}

Angular 4 jquery doesn't work

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() { }}

How to import Javascript file into Typescript

I was wondering how I start the Twitter-Bootstrap from Typescript.
$('.carousel').carousel()
I had to implement jquery.d.ts to fix the $-sign call, but then I'm still getting the error that .carousel() could not be found in jquery.d.ts.
I tried to do this with bundling the javascript to a module and call it like that. But it does not seem to work.
This is my code:
carousel.d.ts
declare module 'carousel/carousel' {
var start: any;
export = start;
}
carousel.js
System.register('carousel/carousel', [], true, function () {
var carousel = function () {
function carousel() {
}
carousel.prototype.start = function () {
$('.carousel').carousel();
}
}
exports.carousel = carousel;
});
app.ts
import {Component} from "angular2/core";
import {bootstrap} from 'angular2/platform/browser';
import {Carousel} from "carousel/carousel";
#Component({
selector: "carousel",
bindings: [CarouselComponent],
templateUrl: 'carousel.html'
})
export class CarouselComponent {
start() {
carousel.start();
}
}
}
bootstrap(CarouselComponent)
Thanks for helping out.
The problem is that you don't have the typing definition for carousel(). Like you mentioned - it's a function in Twitter-Bootstrap, but you only included the typing definitions (*.d.ts) for jQuery. You need to include them for Bootstrap the same way.
You can get the full Bootstrap tying definitions from the DefinitelyTyped project, either from their GitHub or as a NuGet package. Here are the essential parts:
interface CarouselOptions {
interval?: number;
pause?: string;
wrap?: boolean;
keybord?: boolean;
}
interface JQuery {
carousel(options?: CarouselOptions): JQuery;
carousel(command: string): JQuery;
}
I would refactor your carousel.js file like this:
System.register("carousel/carousel", [], true, function(require, exports, module) {
var carousel = function () {
function carousel() {
}
carousel.prototype.start = function () {
$('.carousel').carousel();
}
}
exports.carousel = carousel;
});
Create a file "jquery-caroussel.d.ts" (and add-it to your reference.ts)
inside it:
interface JQuery {
carousel();
}
It will say to the ts compilator than there is a methode carousel() which will be implemented later. (in the browser, by the carousel.js file.)
If you have a similar issue with another lib than carousel, there is plenty of sample of interface here:https://github.com/DefinitelyTyped/DefinitelyTyped
You can import JS files by declaring an ambient module for each library you need. You can have an ambient.d.ts file where you store all ambient module declarations (ie for JavaScript libraries you'd like to import, but for which you do not have the type definitions)
ambient.d.ts:
// You would have a separate module declaration for each JavaScript library
// you want to import for which you do not have any type definitions
declare module 'my-module-i-want-to-import' {
const a : any;
export default a;
}
any other *.ts file that needs my-module-i-want-to-import:
// Include reference to your ambient module declarations
///<reference path="./ambient.d.ts" />
import myModule from 'my-module-i-want-to-import';
// Do something with myModule
console.log(myModule);
In the end, I've changed my code to use the "InjectionToken".
As described here: Use jQuery in Angular/Typescript without a type definition
You can simply inject the jQuery global instance and use it. For this you won't be needing any type definitions or typings.
import { InjectionToken } from '#angular/core';
export const JQ_TOKEN = new InjectionToken('jQuery');
export function jQueryFactory() {
return window['jQuery'];
}
export const JQUERY_PROVIDER = [
{ provide: JQ_TOKEN, useFactory: jQueryFactory },
];
When set correctly in your app.module.ts:
import { NgModule } from '#angular/core';
import { BrowserModule } from '#angular/platform-browser';
import { AppComponent } from './app.component';
import { JQ_TOKEN } from './jQuery.service';
declare let jQuery: Object;
#NgModule({
imports: [
BrowserModule
],
declarations: [
AppComponent
],
providers: [
{ provide: JQ_TOKEN, useValue: jQuery }
],
bootstrap: [AppComponent]
})
export class AppModule { }
You can start using it in your components:
import { Component, Inject } from '#angular/core';
import { JQ_TOKEN } from './jQuery.service';
#Component({
selector: "selector",
templateUrl: 'somefile.html'
})
export class SomeComponent {
constructor( #Inject(JQ_TOKEN) private $: any) { }
somefunction() {
this.$('...').doSomething();
}
}
After Angular's Final Release, (for jquery.js and bootstrap.js)
1) add following npm packages
npm install --save-dev #types/jquery
npm install --save-dev #types/bootstrap
2) in tsconfig.json add following entries in types array,
"types": [
"jquery",
"bootstrap",
]
And now you are good to go now.
Jquery carousel method error in Angular2/typescript

Categories

Resources