Utilizing Imported Functions in Angular for Interpolation - javascript

I have the below component where I am attempting to utilize a function that I've created called FormatDate that displays the date in a particular way. I was expecting to implement it via interpolation in my html however the function is not recognized. Is there a way to utilize it without wrapping it in a function local to the component? I read through the Angular - Template Syntax documents but nothing jumped out to me.
import { Component } from '#angular/core';
import { FormatDate } from '../shared/commonFunctions';
#Component({
selector: 'my-component',
template: '<h3>{{FormatDate(rightNow)}}</h3',
})
export class myComponent {
rightNow = Date();
}
My workaround is below, but it is unsightly to me so I was hoping to find a way around it.
import { Component } from '#angular/core';
import { FormatDate } from '../shared/commonFunctions';
#Component({
selector: 'my-component',
template: '<h3>{{dateFormat(rightNow)}}</h3',
})
export class myComponent {
rightNow = Date();
dateFormat(date: string): string {
return FormatDate(date);
}
}

import {Pipe, PipeTransform} from "#angular/core";
#Pipe({name: 'transformDatePipe'})
export class TransformDatePipe implements PipeTransform {
transform(date: string, params:any...): any {
return yourFunction();
}
}
import { Component } from '#angular/core';
import { FormatDate } from '../shared/commonFunctions';
#Component({
selector: 'my-component',
template: '<h3>{{rightNow|transformDatePipe:anyAdditionalParamsYouNeed}}</h3',
})
export class myComponent {
rightNow = Date();
}
Don`t forget to add your new Pipe to the module declarations array.
https://angular.io/guide/pipes

Related

Angular - trying to use child component function in parent view but I'm gettting an error

When I use #ViewChild I get the error that the component is not defined.
When I use #ViewChildren I get the error that the function from that component is not a function.
I am new to using child components in Angular so I'm not sure why it's doing this when I do have the child component defined in the parent component and when it's clearly a function in the child component.
I don't want to have to define every function from the child in the parent or else what's even the point of using a separate component.
Child Component
import { Component, OnInit } from '#angular/core';
#Component({
selector: 'app-mood',
templateUrl: './mood.component.html',
styleUrls: ['./mood.component.css']
})
export class MoodComponent implements OnInit {
moodColors = ['red', 'orange', 'grey', 'yellow', 'green'];
constructor() { }
ngOnInit(): void {
}
chooseMood() {
alert(this.moodColors);
}
}
Parent Component (Relavant Part of Version with "ERROR TypeError: ctx_r3.mood is undefined")
import { Component, OnInit, ViewChild, ViewChildren } from '#angular/core';
import { ViewEncapsulation } from '#angular/core';
import { MoodComponent } from '../mood/mood.component';
#Component({
selector: 'app-calendar',
templateUrl: './calendar.component.html',
styleUrls: ['./calendar.component.css'],
encapsulation: ViewEncapsulation.None
})
export class CalendarComponent implements OnInit {
#ViewChild('mood') mood: MoodComponent = new MoodComponent;
Parent Component (Relavant Part of Version with "ERROR TypeError: ctx_r3.mood.chooseMood is not a function")
import { Component, OnInit, ViewChild, ViewChildren } from '#angular/core';
import { ViewEncapsulation } from '#angular/core';
import { MoodComponent } from '../mood/mood.component';
#Component({
selector: 'app-calendar',
templateUrl: './calendar.component.html',
styleUrls: ['./calendar.component.css'],
encapsulation: ViewEncapsulation.None
})
export class CalendarComponent implements OnInit {
#ViewChildren('mood') mood: MoodComponent = new MoodComponent;
Parent View
<h2 (click)="mood.chooseMood()"></h2>
You don't explicitly initialize view children via new.
Just use:
#ViewChild('mood') mood : MoodComponent;
If that doesn't work post a Stackblitz example which I can edit to resolve the issue.
Also, using ViewChild is more of an exception in Angular, and your use of it points to a probable design issue. More likely you child component should emit via an Output to the parent.
Regarding outputs, you can do something like this - though it is hard to give a precise answer without deeper knowledge of what you are trying to achieve:
export class MoodComponent implements OnInit {
#Input() moodId: string;
#Output() chooseMood = new EventEmitter<string>();
moodClicked(){
this.chooseMood.emit(moodId);
}
}
export class CalendarComponent implements OnInit {
moodChosen(string: moodId){
console.log(moodId);
}
}
// Calendar template:
<app-mood
moodId="happy"
(chooseMood)="moodChosen($event)"
></app-mood>
1 - you have to use this code
#ViewChild('mood') mood : MoodComponent;
when you are using #ViewChildren it will return list of items with the 'mood' name then you have to use this code
mood.first.chooseMood() ;
its better use ViewChildren when there is ngIf in your element
2- no need new keyword for initialize mood variable
it would be fill after ngOnInit life cycle fires

Value undefined after a function

I have one class with one fuction in it, and another class that will import the first class and use that function. After the function operates i need one value, but i am not getting any value afte the function.
First class:
export class MoveEff {
checkEffect(effectFaceOff1,moveEff1,moveEff2){
if ( effectFaceOff1=== 'grassgrass') {
moveEff1 = 10;
console.log(moveEff1);
}
}
}
Second class :
import { Component, OnInit } from '#angular/core';
import {GenIService} from "../Pokemons/gen-i.service";
import {MovesService} from "../Moves/moves.service";
import {MoveDataClass} from "../MoveDATA/move-data-class";
import {MoveEff} from "../MoveDATA/move-eff";
#Component({
selector: 'app-home',
templateUrl: 'home.page.html',
styleUrls: ['home.page.scss'],
})
export class HomePage implements OnInit {
effectFaceOff1;
moveEff1;
moveEff2;
constructor(private moveeff: MoveEff) {}
this.moveeff.checkEffect(this.effectFaceOff1,this.moveEff1,this.moveEff2);
console.log(this.moveEff1,this.moveEff2);
On the last console.log i should be seeing the 10 value of moveEff1, but it appears undefined.
Why? and how can i solve it?
Exporting the class may not be enough. Try exporting and importing all your methods as modules, or exporting the method directly.
i don't know where you are getting effectFaceOff1, moveEff1 and moveEff2 from, but if they are #Input, their values cannot be retrieved in the constructor.
In that case, you should move your code to the ngOnInit:
ngOnInit() {
this.moveeff.checkEffect(this.effectFaceOff1,this.moveEff1,this.moveEff2);
console.log(this.moveEff1,this.moveEff2);
}
Last but not least, MoveEff should be made an Injectable in order to provide it to your class:
#Injectable({ providedIn: 'root' })
export class MoveEff {
checkEffect(effectFaceOff1,moveEff1,moveEff2){
if ( effectFaceOff1 === 'grassgrass') {
moveEff1 = 10;
console.log(moveEff1);
}
}
}

Adding OpenRouteService to Angular Application on Stackbliz

I added OpenRouteService to my Stackbliz application but cant get it working.
the Component looks like:
import { Component, OnInit } from '#angular/core';
import {Location} from '#angular/common';
import {Openrouteservice} from '/openrouteservice-js/dist/ors-js-client';
#Component({
selector: 'app-event-plan',
templateUrl: './event-plan.component.html',
styleUrls: ['./event-plan.component.scss']
})
export class EventPlanComponent implements OnInit {
constructor(private _location: Location) {
console.log("++++")
console.log(Openrouteservice)
}
ngOnInit() {
}
backClicked() {
this._location.back();
}
}
My problem is that it just doesnt get loaded. I added it as a dependency in the dependency section.
I made the project public here is the url - https://stackblitz.com/edit/angular-micwge?file=src%2Fapp%2Fevent-plan%2Fevent-plan.component.ts
You will have to change the way you import the library. The current way you import is looking for a named export from the library.
If you have allowSyntheticImports and esModuleInterop in your tsconfig.json use this:
import Openrouteservice from 'openrouteservice-js';
otherwise:
import * as Openrouteservice from 'openrouteservice-js';
Find your forked stacknlitz

Theme switcher on localstorage observable service

I implemented a dynamic theme switcher (with tutorial) in my angular app. It work's but when I reload website, the choice is not remembered.
I read about localStorage and i will use it but still doesn't work because I don't know how "where" I should get data from this localStorage, that the choice of the theme will be remembered when I reload the page.
I have this code:
theme.service.ts new version
import { Injectable } from '#angular/core';
import { Subject } from 'rxjs/Subject';
#Injectable()
export class ThemeService {
private _themeDark: Subject<boolean> = new Subject<boolean>();
isDarkFunction() {
let value = localStorage.getItem('isDark');
this._themeDark.next(value);
return this._themeDark.asObservable();
}
isThemeDark = this.isDarkFunction();
setDarkTheme(isThemeDark: boolean) {
this._themeDark.next(isThemeDark);
localStorage.setItem('isDark', JSON.stringify(isThemeDark));
}
}
navbar.component.html
<div class="container-fluid switcher-container">
<mat-slide-toggle [checked]="isThemeDark | async" (change)="toggleDarkTheme($event.checked)">Dark theme</mat-slide-toggle>
</div>
navbar.component.ts
import { Component, OnInit } from '#angular/core';
import { ThemeService } from '../services/theme.service';
import { Observable } from 'rxjs/Observable';
#Component({
selector: 'app-navbar',
templateUrl: './navbar.component.html',
styleUrls: ['./navbar.component.scss']
})
export class NavbarComponent implements OnInit {
isThemeDark: Observable<boolean>;
constructor(
private themeService: ThemeService) { }
ngOnInit() {
this.isThemeDark = this.themeService.isThemeDark;
}
toggleDarkTheme(checked: boolean) {
this.themeService.setDarkTheme(checked);
}
}
app.component.ts
import { Component, OnInit } from '#angular/core';
import { Observable } from "rxjs/Observable";
import { ThemeService } from "./services/theme.service";
#Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.scss'],
providers: [ThemeService]
})
export class AppComponent implements OnInit {
isThemeDark: Observable<boolean>;
constructor(
public themeService: ThemeService) {
}
ngOnInit() {
this.isThemeDark = this.themeService.isThemeDark;
}
}
Please help,
Regards
You might write something like the following in theme.service.ts.
I don't know if it will run flawlessly as is but the idea is to read from localstorage in isThemeDark().
isThemeDark() {
let value = localStorage.getItem('isDark');
this._themeDark.next(value);
return this._themeDark.asObservable();
}
I think it's because you when you do localStorage.getItem('isDark') the result is a string, not a boolean. Maybe try:
let value = JSON.parse(localStorage.getItem('isDark')) === true;
Also check manually if the localstorage is kept after a refresh. Some browsers have a setting to clear everything on refresh.

How to import Javascript library in angular2 globally

I'm trying to import the moment.js library in angular2.
I found the following solution as:
import {Component} from 'angular2/core';
import * as moment from 'moment';
#Component({
selector: 'app',
template: require('./app.component.html')
})
export class AppComponent {
moment:any = moment;
constructor() {}
}
However, I do not want to import this to every component I have. Is there a way to inject it globally so I can use it in all my components?
From what I read here, I can provide the momentjs library when bootstrap the whole application like this:
import * as moment from 'moment';
import {provide} from 'angular2/core';
import {bootstrap} from 'angular2/platform/browser';
bootstrap(App, [
provide("moment", {useValue:moment})
])
Then I can use it in my own component by using DI, like this:
import {Component, OnInit, Inject} from 'angular2/core';
#Component({
selector: 'app',
template: require('./app.component.html')
})
export class AppComponent {
constructor(#Inject("moment") private moment) {}
}
Derive your components from a common base type that imports moment.
Parent
import * as moment from 'moment';
export class MomentAwareClass {
moment:any = moment;
constructor() {}
}
Child
import {Component} from 'angular2/core';
#Component({
selector: 'app',
template: require('./app.component.html')
})
export class AppComponent extends MomentAwareClass {
constructor() {}
}
Update
A better way is to use Dependency Injection to write a service with the Injectable() decorator, this is better as composition is preferred over inheritance.
import { Injectable } from '#angular/core';
import * as moment from 'moment';
#Injectable()
export class SomeClass {
public moment: any = moment;
}

Categories

Resources