Asked  7 Months ago    Answers:  5   Viewed   40 times

I have this module which componentize the external library together with additional logic without adding the <script> tag directly into the index.html:

import 'http://external.com/path/file.js'
//import '../js/file.js'

@Component({
    selector: 'my-app',
    template: `
        <script src="http://iknow.com/this/does/not/work/either/file.js"></script>
        <div>Template</div>`
})
export class MyAppComponent {...}

I notice the import by ES6 spec is static and resolved during TypeScript transpiling rather than at runtime.

Anyway to make it configurable so the file.js will be loading either from CDN or local folder? How to tell Angular 2 to load a script dynamically?

 Answers

83

If you're using system.js, you can use System.import() at runtime:

export class MyAppComponent {
  constructor(){
    System.import('path/to/your/module').then(refToLoadedModule => {
      refToLoadedModule.someFunction();
    }
  );
}

If you're using webpack, you can take full advantage of its robust code splitting support with require.ensure :

export class MyAppComponent {
  constructor() {
     require.ensure(['path/to/your/module'], require => {
        let yourModule = require('path/to/your/module');
        yourModule.someFunction();
     }); 
  }
}
Tuesday, June 1, 2021
 
huhushow
answered 7 Months ago
91

In your controller, add a function to to handle the 'onLoad' event, setting the state to {loading: false}:

loading: boolean = true
onLoad() {
    this.loading = false;
}

In your template, render a loading gif (or whatever you want) while the state has loading === true, the tricky part is that you should just hide the img element with [hidden]="true/false" as opposed to prevent it from rendering so it will actually load the src, then just bind the onLoad function in your controller to the (load) event on the actual image:

<img *ngIf="loading" src="/assets/loading.gif" alt="loading" />
<img [hidden]="loading" (load)="onLoad()" src="{{ source }}" />

This solution is functionally the same as AngJobs's, but it's more declarative and a little less cumbersome IMO.

PS: Using [hidden]="boolean" instead of *ngIf is a bit of a gotcha, you should look to http://angularjs.blogspot.com/2016/04/5-rookie-mistakes-to-avoid-with-angular.html to understand why and for a solution on how to apply it safely.

Thursday, July 29, 2021
 
elias
answered 5 Months ago
89

You can use javascript in the Angular application.

Step 1. Create demo.js file in assets/javascript folder.

export function test1(){
    console.log('Calling test 1 function');
}

Step 2. Create demo.d.ts file in assets/javascript folder.

export declare function test1();

Step 3. Use it in your component

import { test1 } from '../assets/javascript/demo'; 
 @Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent {
  constructor() {
    console.log(test1());
  }
}

Note: js and .d.ts file name should be same

Wednesday, August 4, 2021
 
mario
answered 4 Months ago
26

ES modules cannot replace Angular modules and DI. They compliment each other and keep the application modular and testable.

ES6 modules provide extra layer of extensibility, for example controller/service subclassing (something that doesn't look good with Angular modules and DI alone).

The recommended approach with ES6 or TypeScript is to do DI conventionally, with $inject annotation:

export class PostsService {
  static $inject = ['$http'];
  constructor(
    public $http: angular.IHttpService
  ) {}
  ...
}

It's also a good practice to have one module per file, this way the application stays modular and testable:

export default angular.module('app.posts', [])
  .service('posts', `PostsService)
  .name;`

Its default export is module name that can be imported in another module that directly depends on it:

import postsModule from '...';
...
export default angular.module('app.controller', [postsModule])
  .controller('controller', Controller)
  .name;`

Application injector cannot be normally reached from a decorator. Even if it's possible with a hack to make it work in production, it will be messed up in tests.

angular.injector creates new injector (i.e. application instance) and has very limited proper uses in production:

angular.injector(['ng']).get('$rootScope') !== angular.injector(['ng']).get('$rootScope');

It is often misused when a developer doesn't know how to get current $injector instance. It certainly shouldn't be used in a case like this one.

Saturday, August 7, 2021
 
MikeMcClatchie
answered 4 Months ago
91

You can use some method and destructuring.

let roles = [ {roleId: "69801", role: "ADMIN"}, {roleId: "69806", role: "SUPER_ADMIN"}, {roleId: "69805", role: "RB"}, {roleId: "69804", role: "PILOTE"}, {roleId: "69808", role: "VENDEUR"}, {roleId: "69807", role: "SUPER_RB"} ]

const checkRoleExistence = roleParam => roles.some( ({role}) => role == roleParam)

console.log(checkRoleExistence("ADMIN"));
console.log(checkRoleExistence("RA"));
console.log(checkRoleExistence("RB"));
Friday, October 15, 2021
 
akes406
answered 2 Months ago
Only authorized users can answer the question. Please sign in first, or register a free account.
Not the answer you're looking for? Browse other questions tagged :  
Share