Angular 4 component : call javascript/jquery code from another file - javascript

i have a jquery code which gets executed at ngAfterViewInit()
//myComponent.ts
ngAfterViewInit() {
$(function () {
$('#myElement').click(function (e) {
//code working fine here
});
}
but i want to move it to an external myScripts.js to simplify the component
i tried moving tthe code to an external file then use import but this makes the script to be called only once so if i navigate to a child component (which erases the html element myElement with the onclick defined ) then back to the parent myElement is back without the onclick event
so the question is :
what is the best practice to use jquery/javascript with angular4

You need to export your function from myScripts.ts and then import it and call it within ngAfterViewInit().
After exporting correctly you should be able to do:
// app.ts
import { myInitFunc } from './myScripts';
ngAfterViewInit() {
myInitFunc();
}
// myScripts.ts
export function myInitFunc(): void {
$(function () {
$('#myElement').click(function (e) {
//do stuff
});
}
};
Take a look at export: https://developer.mozilla.org/en/docs/web/javascript/reference/statements/export

Related

How is this inheritance working in JavaScript?

Watching a React course, he wanted to extract a Component into a more reusable component, My question/confusion is about this line below:
this.doSubmit(); that how does it even not error? because doSubmit() is in the CHILD class. It is not defined in the parent class. So shouldn't it error?
class Form extends Component {
handleSubmit = (e) => {
e.preventDefault();
// bunch of code then next line is my question:
this.doSubmit();
};
}
class LoginForm extends Form {
doSubmit = () => {
// call server
console.log("submitted");
};
}
Since you mentioned this is a course, I suspect there might be something more. But based on what you provided, this will not work: exactly as you said, the method is in child class.
I created a sample and you will see the error when call handleSubmit(): https://codesandbox.io/s/thirsty-buck-zpgll?file=/src/App.js

Storybook: callback when a story has been rendered

I'm working with Storybook for components creation in pure HTML, CSS and JS (jQuery actually).
I'm wondering if there's a callback function when a story is rendered on the screen (like useEffect for React) because I need to run then the relative jQuery code only when the component is really in the DOM.
Here's my situation:
// Button.stories.js
// my pure HTML component
const Button = () => `<button>My button </button>`;
export default {
title: 'Buttons',
};
export const ButtonStory = () => Button()
// would be great something like: ButtonStory.callback = function(){ do this}
There's something without workaround? (Like wrap the HTML component inside react component and use useEffect for trigger the code)
Thanks
I'll share a not optimal solution I've found but maybe could be useful for others:
MyStory.stories.js
import {ActionBar} from '../public/components/ActionBar/actionbar.module';
import controller from "!raw-loader!../public/components/ActionBar/controller.js";
import customRenderStory from "../utils/customRenderStory";
export default {
title: 'Basic/ActionBar',
};
//
export const ActionBarToExport= () =>
customRenderStory(
ActionBar(),
controller,
2000
);
customRenderStory.js
export default (component, javascript, timeout) => {
if (javascript !== undefined) setTimeout(() => eval(javascript), timeout)
return component;
}
In this way, I can execute the code inside controller.js each time the story is rendered. I need a timeout (which can be configured) because I can't be sure that the component will be mounted after the code execution.
In my case, StoryBook in plain HTML and jQuery, seems is working.

Write global functions to use in all components in angular

Note : Its not for global variable but for a global common function to perform a functionality on all components
I am working on an angular app where I have around 400 components in different modules, almost all components have one same kind of functionality as mentioned below
There is a sections on many pages which shows a "How to work section" which can be closed by users and will remain closed unless they open it again, I have done it with cookies which I set on click on close or open icon but this function is written in a component and this needs to be imported in other components
I want to create a functions somewhere which perform this functionality on click on icon and can be called without importing any component in others.
One way to do it ( as I thought ) could be create a JavaScript function in a file and load it in index file and then call this function on click on close and open icon
Not sure if this is the best way to do this. Hope someone will come up with a better solution.
1. create your global function service, i.e. 'funcs.services.ts' under 'services' directory:
import { Injectable } from '#angular/core';
#Injectable({
providedIn: 'root'
})
export class FuncsService {
constructor() { }
myGlobalAddFunction(a){
return a++;
}
mySecondFunc(){
// add more... and so on
}
}
2. Import the function in your component:
// your path may different
import { FuncsService } from './../services/funcs/funcs.service';
//...
constructor(
private funcs: FuncsService
) {}
ngOnInit(): void {
let x = 1;
myResult = this.funcs.myGlobalAddFunction(x);
// Then you are expecting 2 for return value
}
3. Hope that works... :)
You can export a function that is a written in .ts file and then call it in all your components.
export function myFunction(){
// Do something
}
And then import the function myFunction() in other components. That works fine for me and can be useful in certain cases
This isn't the best solution (in my opinion). The best solution would be to either create a service, or an utils class.
But if you want to do this, I suggest you make a JS file, that you declare in your angular-cli.json file under the scripts property, containing your functions.
EDIT Now that you've came back to reason, here is a code sample to make utils classes.
export const IMG_UTILS = {
convertPngToJpg = (picture: any) => {
// Your logic here
}
};
export const VIEW_MANAGER = {
isAdblockActive = () => {
// test if an ad-blocker is active
}
};
You can make any utils class you want in a const, then put it into a file. Then, you can put this file in an utils folder, and request it with
import { VIEW_MANAGER } from 'src/app/utils/view-manager';
Otherwise, you can make a service, which is handled by Angular, with a console command such as
ng g s services/view-manager/view-manager
And it will behave the exact same way : you will import it in your components to use it.
Hope this helps !
The most recommended way is to use a service and inject it whenever needed, but there is a way to have a function available globally.
Although I don't think it's a really good idea, you can add the function in the index.html file, then whenever you want to use it, you have to use #ts-ignore to avoid an error from being thrown.
e.g
index.html
<script>
function globalFunc(){
alert(2)
}
</script>
anywhere else on the app
// #ts-ignore
globalFunc();
List item
Just to chime in with possibly a duplicate answer albeit more fleshed out... I have a utilities class which I use.
For example:
export class Utilities {
// Simple promise wrapper for setTimeout. See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Using_promises#creating_a_promise_around_an_old_callback_api
public static Wait = (ms: number) => new Promise((resolve) => setTimeout(resolve, ms));
}
The class is referenced in a component via the import statement:
import { Utilities } from 'path/to/Utilities';
And then you can call your static methods thus:
Utilities.Wait(30000)
.then(() => DoStuff())
.catch(() => console.log('Darn!'));
I would tend to use RxJs but I've written it this way to keep things a little cleaner.

How to properly import namespaced code used in Webpack/es6/babel?

I'm currently working on a ReactJS project and I'm trying to come up with an effective way to namespace my code. The most obvious solution I have is to do the following:
let API = {
init: function() {
// Do some type of initialization here
}
makeACall: function() {
// Make a call
}
};
Previously, I'd make a file of functions each of which were exported like:
export function makeACall() {
// Make a call
}
And then I'd import it into another file using: import { makeACall } from 'utils/api';
However the problem here is that I may have another function in the imported file called makeACall. So what I'd like to do is namespace it. Question is: how do I import individual functions from an object/namespace or is this not possible?

Call a Aurelia function from <script>

In my Aurelia view I have a script tag from where I want to call a function from my view-model:
Page.html:
<template>
...
<script>
function beginEdit(args) {
console.log(args);
console.log(args.primaryKeyValue);
//In this place I want to call the sayHello() fuction
};
</script>
</template>
Page.js:
import {inject} from 'aurelia-framework'
import {HttpClient} from 'aurelia-http-client';
import {Router} from 'aurelia-router';
export class Licigrid{
constructor(){...}
activate(){...}
...
sayHello()
{
alert("Hello");
}
}
I tried to use inside my script tag ${sayHello();} but this calls the function immidiately when the page has loaded and not when the user has entered in the beginEdit() function.
I have reproduced this piece of code in Plunker.
Note that I am using a package that calls the beginEdit function by itself, so unfortunately I can not use .trigger(), .delegate(), or .call() inside my html tag which would solve my problem.
My question is: is there a solution to call the sayHello() function from my script tag?
The beginEdit function needs access to the App view model instance. We can use Aurelia's DI container to retrieve this:
var app = container.get(App);
app.sayHello();
Problem is we don't have access to the container within the beginEdit function. We can use a small hack to access the container:
var container = document.body.aurelia.container;
We also need the App constructor function because it's the key to retrieving the app instance from the container. We can use the System loader to load the module containing the App constructor function:
System.import('app').then(function(module) {
var App = module.App;
});
All together it looks like this:
function beginEdit() {
System.import('app').then(function(module) {
var App = module.App, // get the constructor function
container = document.body.aurelia.container, // get the container
app = container.get(App); // get the instance of App (the viewmodel)
app.sayHello();
});
}
Here's the working plunkr:
http://plnkr.co/edit/9c0oJmifjW5pXXdD06Hg?p=preview

Categories

Resources