How can I re-execute an external script in Angular? - javascript

I have an external js file with a bunch of jQuery methods for the user interface. However, the Angular router is asynchronous, so user interface elements on other pages do not get properly rendered by the script, since they don't yet exist in the DOM.
Formerly, I was cherry picking some methods from the script and adding them to a method called rerender, but this is becoming cluttered.
My question was to see if there is a way to load and execute the entire script again inside of the rerender method?

You can import external scripts. Do it inside the constructor:
constructor() {
System.import('script-loader!bower_components/fullcalendar/dist/fullcalendar.min.js').then(()=>{
this.render(); // Do whatever, for demonstration I call a render() method
})
}
Make sure in your custom-typings you have declared System:
declare let System: SystemJS;
interface SystemJS {
import: (path?: string) => Promise<any>;
}
interface GlobalEnvironment {
SystemJS: SystemJS;
System: SystemJS;
}
Option 2:
Alternatively, you can put this into your module after the import statements:
require('bootstrap/js/tooltip.js'); // For example

Related

How to use Vue-plugin-load-script

I am trying to load a custom JS file into my vue and I recently came across vue-plugin-load-script and installed it. I configured it as below:
In my main.js I have
Vue.loadScript("file.js").then(() => {
console.log("SUCESS")
}).catch(() => {
console.log("FAILED")
})
however, the npm page does not show how to use your functions in your views. For instances, lets say the file.js had a function called calculateTime(), and I have a view called Home.vue. How would I call the calculateTime() function from my
<script>
export default {
methods : {
** Trying to put function here **
}
}
</script>
If you have you JS File local, you can import it, like:
import * as localA from "./../../theFile.js"; /*put your path to file.js*/
And after that you can use all methods from theFile.js by writting in a method from your vue Component
methodVue: function (...) {
localA.theMethod(param); /*the Method is declared in theFile.js*/
return;
}
And in your theFile.js your method that you want to use need to be written like that
export function theMethod(param) {
...
}
Do you have a specific reason to use this library? Looking at the function all it does is add a script tag to the DOM if it is not already there and resolve the promise when it loads GitHub link. You could just as well use import * from 'file.js' at the top of the vue file. Then use the functions from that file as usual. The bundler should be able to figure out if the file is imported in multiple places and add it only once.

A list of the namespaces created by import statements

I've a script tag (type="module"), which is dynamically populated with import statements by PHP based on some parameters. The populating process is controlled by the authorization system of the site, and it can drop some imports from the script, depending on the rights of the current user.
An example of the final rendered script tag on a page:
<script type="module">
import ui from 'path_to_ui_module';
import read from 'path_to_read_module';
import edit from 'path_to_edit_module'; // Could be omitted by the authorization
import create from 'path_to_create_module'; // Could be omitted by the authorization
import delete from 'path_to_delete_module'; // Could be omitted by the authorization
ui.init();
</script>
All the imports are guaranteed to be objects only.
Now, the problem lies in ui.init method, where I want to assign some references of some properties of the loaded modules (and their submodules) to a property in ui, but I don't know, which modules are actually loaded, because the authorization system may have dropped some of the modules from the script. For example, all the loaded modules have a cmd object containing various methods, and I'd like to assign a reference to those methods to ui.cmd object. How can I iterate through all the namespaces of the imported modules, including the possible submodules imported by the modules loaded in the script?
Currently I've modified the authorization system to create the ui.init call, which passes the references of the really loaded modules to ui.init method, but the submodules are naturally not included.
ui.init({modules: {read: read, edit: edit, create: create, delete: delete});
(The modules dropped by the authorization system are not included in modules object.)
With the passed modules object, a simplified ui.init method looks like this ("main module" in the comments is ui, "submodule" refers to the modules passed via the arguments):
init (options) {
for (const module in options.modules) {
this[module] = options.modules[module]; // Add submodule reference to the main object
this[module].main = this; // Add main module reference to submodule
Object.assign(this.cmd, this[module].cmd); // Assign the cmd methods of the submodule to the main module's cmd object
this[module].init(); // Initialize the submodule
}
}
Reformed question: Is there a native "list" of all imported modules, including the submodules the imported modules have imported, available, that I can use instead of options.modules in the for .. in loop? Or alternatively, is there a way for the submodules to somehow "expose" themselves after they've been loaded, so that they can create a list of the loaded modules?
You can try using dynamic imports:
(I am assuming that your PHP script can dynamically generate the .then callback)
<html>
<body>
<script type="module">
Promise
.all
( [ import('./node_modules/the-answer/dist/the-answer.es.js')
, import('./node_modules/the-answer/dist/the-answer.es.js')
, import('./node_modules/the-answer/dist/the-answer.es.js')
]
)
.then(([{default: answer1}, {default: answer2}, {default: answer3}]) => {
// You now know all the modules that have loaded 😊
console.log(answer1, answer2, answer3);
});
</script>
</body>
</html>
Because the dynamic form of import returns a promise, you can wait for all of them to resolve and have access to them.
The the-answer module is literally this:
export default 42;
Which is why I need to destructure each module in the .then() method, e.g.
.then(([{default: answer1}]) => alert(answer1))

When does the code outside React Component class in a JS file run?

Say I have a JS file contains 2 React Component class definition and a bunch of other things:
// a file called OuterComponent.react.js
import xxx from xxx;
import yyy from yyy;
// When does these run?
let a = 0;
a = 1;
export default class OuterComponent extends React.PureComponent<> {
render() {
return (
<View>
<InnerComponent />
</View>
);
}
}
class InnerComponent extends React.PureComponent<> {
//... something
}
Questions
When will the declaration and value setting code for 'a' run? Does it run when this file is imported/required by other files?
Can I have some flag in this file and changes from time to time, and then read the value of this flag from many other files? (like a singleton manager?) If I can, how do I export it and import it?
What does creating multiple files actually mean? (except that it breaks huge chunk of code into small chunks for better readability) Does it make any other difference?
Question 1: When will the declaration and value setting code for 'a' run? Does it run when this file is imported/required by other files?
Runs the first time the file is imported. It is not executed on subsequential imports.
Question 2: Can I have some flag in this file and changes from time to time, and then read the value of this flag from many other files? (like a singleton manager?) If I can, how do I export it and import it?
You can.
Exporting:
export let a = 0;
Importing:
import { a } from './filename.js';
Question 3: What does creating multiple files actually mean? (except that it breaks huge chunk of code into small chunks for better readability) Does it make any other difference?
Breaks code into small chunks;
Allows reuse; and
Enables encapsulation of non-exported variables/functions.
--
Check a demo of modules usage: http://plnkr.co/edit/0ImgQj2KzLj9O1D63Gq9?p=preview
Notice how a.js is loaded only once, even though it is imported both by b.js and c.js. Also see how it is exported and imported, and how when it changes, the change is picked up in other modules.
okay here it is
Answer 1: Yes, it runs when you import this file.
Answer 2: You can define some varible and export it to use in some other file, but that we do for constant values that does not change over time, like your action types etc, the thing you are referring to here is not what it is for, you want to use react Context or Redux store for that.
Answer 3: Creating multiple files is a modular approach to code, React emphasis on Composition that is the whole point of composing components in one another and build an App
Yes. This code will run immediately when the file is imported. It has nothing to do with react but with how js works.
You can share a variable in js using export keyword like this:
export let a = 0
Changes to this variable won't rerender your components because it's not part of any state.
Readability is huge impact by itself. It also allows reuse of variables names.
When working in collaboration it makes the flow much easier and reduces conflicts to only the places where they really are.

Where to store common component methods in #NUXT.JS

Actually i want to know where to store common components methods in #NUXT.JS.
things which i have tried.
--> Storing common code in middleware (its use-less) because according to my knowledge middleware is only capable of handling request and response to server.
methods: {
// states methods.
SwitchManager: function (__dataContainer, __key, __value) {
// stand alone debugger for this module.
let debug = __debug('computed:_3levelSwitch')
// debug showing function loaded.
debug('(h1:sizeCheck) creating switch..')
// switch.
switch (__key) {
// fake allow set value to true of given key
default:
this[__dataContainer][__key][__value] = true
break
}
return this[__dataContainer][__key][__value]
},
SizeCheck: function (__size) {
// stand alone debugger for this module.
let debug = __debug('tags:p')
// debug showing function loaded.
debug('(p:sizeCheck) checking..')
// init switch.
this.SwitchManager('pill', 'size', __size)
},
StateCheck: function (__state) {
// stand alone debugger for this module.
let debug = __debug('tags:h1')
// debug showing function loaded.
debug('(h1:sizeCheck) checking..')
// init switch.
this.SwitchManager('pill', 'state', __state)
}
},
created () {
// h1 tag size check
this.SizeCheck(this.size)
this.StateCheck(this.state)
}
I go for mixins like with plain vue.js. Only difference - for global mixins - I include them as a plugin, but first:
Non global mixins
I would create an extra folder for my mixins. For example in a /mixins/testMixin.js
export default {
methods: {
aCommonMethod () {}
}
}
Then import in a layout, page or component and add it via the mixins object:
<script>
import commonMixin from '~/mixins/testMixin.js'
export default {
mixins: [commonMixin]
}
</script>
Global mixins
For example in a new file plugins/mixinCommonMethods.js:
import Vue from 'vue'
Vue.mixin({
methods: {
aCommonMethod () {}
}
})
Include that file then in nuxt.config.js
plugins: ['~/plugins/mixinCommonMethods']
After that you would have the method everywhere available and call it there with this.commonMethod(). But here an advice from the vue.js docs:
Use global mixins sparsely and carefully, because it affects every single Vue instance created, including third party components. In most cases, you should only use it for custom option handling like demonstrated in the example above. It’s also a good idea to ship them as Plugins to avoid duplicate application.
Inject in $root & context
Another possibility would be to Inject in $root & context

TypeScript: access global var from a class without import

I got this module like this:
module MyModule {
export class Constants {
public static WIDTH:number = 100;
public static HEIGHT:number = 100;
....
}
}
export = MyModule;
Now I need to use MyModule.Constants.WIDTH in another class but I can't use import (I need to deliver this class js to a third party, and they don't use requirejs). Right now I use reference to get code checking but it keep giving this error (at transpilling time)
error TS2095: Could not find symbol 'MyModule'
What should I do now so I can use autocomplete and get rid of this error?
I hope you're not mindplay on the TypeScript forum otherwise I'm about to repeat myself.
export and import work together. You should either be using both or neither. If you check what the generated code looks like with and without the export keyword you'll see that export causes a module to be built. Since the third party can't use RequireJS I don't think this is what you want.
I would structure my classes like the following:
// file pkg/Foo.ts
module company.pkg {
export class Foo {}
}
// file pkg2/Bar.ts
module company.pkg2 {
export class Bar{}
}
Putting everything into the name space of your company minimizes the chance of a conflict with another library. Classes know about each other using a reference /// <reference path="..." /> which will allow it to compile.
Since you're not doing modules I would also compile to a single file using --out filename.js. That gets all the files included in (usually) the right order.

Categories