Angular 7 Dynamic variable name for imported component - javascript

In a simple angular app, I have created a test component like the one below:
test.component.ts
import { Component } from '#angular/core';
#Component({
selector: 'test',
template: `<h1>I am a test</h1>`,
styles: [`h1 { font-family: Lato; }`]
})
export class TestComponent {
}
which I import in my app module like this:
app.component.ts
import { Component } from '#angular/core';
import { TestComponent } from './test.component';
#Component({
selector: 'my-app',
templateUrl: './app.component.html',
styleUrls: [ './app.component.css' ]
})
export class AppComponent {
name = 'Angular';
public TestComponent = TestComponent;
dynamic = "Test";
constructor(){
console.log(TestComponent);
console.log(this.TestComponent);
console.log(this['TestComponent']);
console.log(this[this.dynamic + 'Component']);
}
}
Getting help from this topic Angular 5 Dynamic variable name, I was able to get my component name dynamically (in the real example, the dynamic variable changes depending on an API call response).
My question is if there is any way to achieve the same result without having to pass the component as a local class variable, thus avoiding this line
public TestComponent = TestComponent;
without the this keyword the dynamic variable is not working, it gives me an error
console.log([this.dynamic + 'Component']);
I tried adding the code in a stackblitz but cannot seem to be able to share it (https://github.com/stackblitz/core/issues/215), but it is quite simple to copy the two files in a new empty stackbitz (https://stackblitz.com/edit/angular-f4ars5) to replicate.
Thanks in advance.

First you need to understand the following line
this['TestComponent']
In javascript you can access class properties in two ways. Class.property or Class["property"]. So when you are writing this["TestProperty"] you are effectively saying, Get AppComponentInstance.TestProperty
So console.log([this.dynamic + 'Component']); is like writing .TextComponent with nothing on the left side.
Now based on this, what are you trying to achieve exactly? Get the type or an instance of the type? What do you want to use the type for?
What you could do though would be to declare somewhere another global class and have these properties in them. Check this one for global variable declaration.
Your json could be something like this:
export class ComponentMapping
{
private TestComponent = TestComponent;
}
And then in your class access the test component accordingly.

Related

use JavaScript function in angular app.component.ts

i have a js file action.js and i want to use javaScript in angular. so when i read about it, it says that js file must be put in assets and the path must be refered in scripts array in angular.json and then using declare in ts and ngOnInit but this raises an error that the function is undefined beside that is forbidden to access the js file and MIME type checking is enabled
here is my js file function
function Di(){
console.log('ffffffffffffff');
}
the app.component.ts
import { AstMemoryEfficientTransformer } from '#angular/compiler';
import { Component, OnInit } from '#angular/core';
declare function Di(): any;
#Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.scss']
})
export class AppComponent implements OnInit{
title = 'Calculator';
ngOnInit() {
Di();
}
}
angular.json
"styles": [
"src/styles.scss"
],
"scripts": ["src/assets/js/action.js"]
},
app.component.html
</div>
</div>
<script src = "/src/assets/action.js"></script>
</body>
thanks in advance
want to use js functions in angular
Try to create a di.ts file and export your function inside
export default function Di(){}
then import it into your AppComponent
import Di from 'di'
Create a ts file instead of js and then create your function like this
export fuction Di() { console.log('Di') }
then import it into your component.
If this works for you I would like you to inform me, please.
Not sure that I understand the sense of this function - should it be executed by click? Or with component creation?
Assuming that with on button click from html template,.you should add this fn as a public field into component and call it with parentheses from html

this binding in Angular vs React

I am just Starting React ,i got the concept why should we bind this in React but How Angular is Taking care of this i am Confused
React
class Product extends React.Component {
a= "mdb"
constructor(props) {
super(props);
// this.handleUpVote = this.handleUpVote.bind(this)
}
// Inside `Product`
handleUpVote() {
console.log("we are looking at This",this.a) //undefinded
this.props.onVote(this.props.id);
}}
Angular
import { Component } from '#angular/core';
#Component({
selector: 'my-app',
templateUrl: './app.component.html',
styleUrls: [ './app.component.css' ]
})
export class AppComponent {
name = 'Angular';
ngOnInit(){
this.checkName()
}
checkName() {
console.log(this.name) // OP- angular
}
}
How this worked in Angular Without .bind(this) or Arrow Function of Es7 What did i miss ?
It's not about angular or react. It's just the behavior of this in javascript that you have to bind it explicitly or use arrow functions which uses lexical this binding which automatically binds them to the scope they are defined in. And TypeScript is pretty good at finding the “nearest object” or knowing the lexical scope, so TypeScript can give you exact information on what to expect from this. here it's explained good or here to understand this' behavior in javascript and react.

Access function defines in JavaScript file from TypeScript file

I have a function X within a JavaScript file “MyFile.js” in the following path of an Angular 4 project : /assets/js/MyFile.js
I already added the path in the angular-cli.json into the scripts section.
...
“scripts”:
[ “assets/js/MyFile.js”]
...
Question: How can access the function X in MyFile.js from a typescript component?
I don't believe that you can call a function from a script added via .angular-cli.json, although you can implement IIFEs that way. Normal usage is for external libraries (bootstrap.js, collapse, animations and the like) as they get added as <script> tags in the index.html.
Rather than adding it to your angular-cli.json, it's easier to import it in your components
Give MyFile a .ts extension to avoid having to pass the --allowJs flag. E.g., MyFile.ts
Make sure to export your functions. If you have several, you might put them in a class and make them static (but that's a different question). Here's what I did:
_
// myfile.ts
export const myFunction = () => {
console.log('hello');
};
_
Import the script into the desired component via import { myFunction } from '../assets/js/myFunction'
_
import { Component, OnInit } from '#angular/core';
import { myFunction} from '../assets/js/myfile';
#Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent implements OnInit {
title = 'app';
ngOnInit() {
myFunction();
}
}
_

Angular: call function from other component

I'm trying to make two angular components and I want to call a function from the first component in the second component. When I try this I get following error message: Cannot red property 'functionName' of undefined. How can this be solved?
Here a link of an example: https://stackblitz.com/edit/angular-rre4gb
That's because the component you want to call its function, is not instantiated.
for component communication you can use a service instead:
Service
#Injectable()
export class MyService {
myCustomFunction(){
}
}
Component
in your component:
#Component({
selector: 'my-component',
providers: [ MyService ]
})
export class MyComponent {
// inject your service to make it available
constructor(private service: MyService){}
doStuff(){
// call function which is located in your service
this.service.myCustomFunction();
}
}
As others have stated, I would prefer a shared service with a Subject among these components.
service:
#Injectable()
export class SharedService {
mySubject = new Subject();
}
WorldComponent (subscriber):
export class WorldComponent {
constructor(private sharedService: SharedService){
this.sharedService.mySubject.subscribe((data)=>{
this.worldFunction();
})
}
HelloComponent(publisher):
public helloFunction() {
alert('Hello');
this.sharedService.mySubject.next(true);
}
You can find the updated example here: https://stackblitz.com/edit/angular-rnvmkq?file=app%2Fworld.component.ts
The best way to share information between multiple components is generally through a service.
Create a separate file: file.service.ts
Provide the service in the app.module.ts file
Inject the service into each component. Then you'll have access to the variables in both components
See this: https://angular.io/tutorial/toh-pt4
the reason of the error is that the hello component is not imported, but instead of calling a component from another, you should use a service in between, as other answers already suggested.

Injecting angular1 service in angular2 directive

I'm reading lots of articles on this matter like this, and this and also this but each one of these articles starts from a situation in which the NG1 service is a class and can be exported.
I'm in a very different situation, i often have multiple services in the same file and they are defined in a very old style manner like
angular.module('App.services').factory('SessionService',
function() {
var defer = $q.defer();
[...]
}
);
No class, no export.
And this stuff is directly linked in the page with an old fashioned <script src="...">
At the same time i'm trying to create new directives in Angular2 and these directives need those old fashioned services.
I get i should be able to write something like this
import {Injector,Component, Directive, ElementRef, Input, View} from 'angular2/core';
var injector = Injector.resolveAndCreate([
SessionService
]);
var SessionService = injector.get(SessionService);
#Component({
selector: 'nav-bar'
})
#View({
templateUrl: '/app/components/navbar/navBar.html'
})
export class navBar {
constructor() {
}
}
but of course SessionService object is not found.
How can i get out of this mess?
[Additional Info]
Using babel as transpiler
angular2-annotations plugin added
A great article to understand the difference between Annotations and Decorators in angular2: http://blog.thoughtram.io/angular/2015/05/03/the-difference-between-annotations-and-decorators.html
You simply need to leverage #Inject:
#Component({
selector: 'nav-bar'
templateUrl: '/app/components/navbar/navBar.html'
})
export class navBar {
constructor(private #Inject('SessionService') sessionService) {
}
}
See this plunkr for more details: http://plnkr.co/edit/U6ygjUUQ04mTGAAaC1pZ?p=preview
You can notice that with factory you can't use classes. It's only possible with services...
If you use ES6 only, you could try this:
#Component({
selector: 'nav-bar'
templateUrl: '/app/components/navbar/navBar.html'
})
export class navBar {
constructor(sessionService) {
}
static get parameters() {
return [[ new Inject('...'), new Inject('...') ]];
}
}

Categories

Resources