Angular9: Import of service not found in component - javascript

I've created a service that I use in 2 separate components from the same module.
The service has a few imports and is somewhat normal.
import { CdkPortal } from "#angular/cdk/portal";
import { ElementRef, Injectable } from "#angular/core";
import { Subject, Subscription } from "rxjs";
#Injectable()
export class TestService {...}
I've added the service into the module into the providers array as well as both components where the service is needed.
The first component uses the service with no issue.
import { FlyoutService } from "../flyout.service";
#Component({
selector: "test-uno",
templateUrl: "./test-uno.component.html",
styleUrls: ["./test-uno.component.scss"],
})
export class TestUnoComponent implements OnInit, OnDestroy, AfterViewInit {
constructor(private flyoutService: FlyoutService) {...}
}
The second component, that uses the service in what I think is the same way, fails.
import { FlyoutService } from "./../flyout.service";
#Component({
selector: "test-dos",
templateUrl: "./test-dos.component.html",
styleUrls: ["./test-dos.component.scss"],
animations: [...],
})
export class TestDosComponent implements OnInit, OnChanges, OnDestroy {
constructor(private flyoutService: FlyoutService) { }
}
The second component fails in the browser with the error:
Export of name 'CdkPortal' not found.
This only happens when buildOptimizer is set to true on the build. Any idea what's going on?

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

Angular programmatic navigation - Why router does not in providers array

In Angular Dependency Injector when ever we injecting a Type , we will includes them in providers array (May be in #NgModule decorator or #Component decorator. But in the following instance when we navigate programmatically we inject Router instance to constructor, But we don't provide in providers array as normally we do in Angular Dependency Injector.
What is the different here than Angular Dependency Injector ? for your reference I will attach both code
Programmatic Navigation - Code
import { Router } from '#angular/router';
#Component({
selector: 'app-home',
templateUrl: './home.component.html',
styleUrls: ['./home.component.css']
})
export class HomeComponent implements OnInit {
constructor(private router:Router) { }
ngOnInit() {
}
onLoadServer(){
this.router.navigate(['servers']);
}
}
Angular Dependency Injector way - Code
import { Component,Input} from '#angular/core';
import { LoggingService } from '../logging.service';
#Component({
selector: 'app-account',
templateUrl: './account.component.html',
styleUrls: ['./account.component.css'],
providers:[LoggingService]
})
export class AccountComponent {
#Input() account: {name: string, status: string};
#Input() id: number;
constructor(private logginService:LoggingService){
}
onSetTo(status: string) {
this.logginService.loggingStatusChange(status);
}
}
RouterModule.forRoot already injects Router in root injector, thats why you don't have to include it in providers array any where. you can read about it here :-
https://angular.io/api/router/RouterModule#forroot

function share in header and sidebar component angular 6

I need to sidebar component function in sidebar.
my header component
import { Component, OnInit, Input,ViewChild } from '#angular/core';
import { SidebarComponent } from '../sidebar/sidebar.component';
#ViewChild(SidebarComponent) SidebarComponent;
ngOnInit() {
this.SidebarComponent.testFunction();
}
sidebar component
testFunction() {
console.log('value');
}
I added an essential code block for the understanding purpose. when I use the above code error said,
ERROR TypeError: Cannot read property 'testFunction' of undefined
at HeaderComponent.push../src/app/layout/components/header/header.component.ts.HeaderComponent.ngOnInit (header.component.ts:57)
can u help me to fix this issue?
call it after child view is initialized.
#ViewChild(SidebarComponent) sidebarComponent: SidebarComponent;
ngAfterViewInit() {
this.sidebarComponent.testFunction();
}
For sharing of functions in Angular, it is better to use a service and call it's functions in both of the components.
import { Injectable } from '#angular/core';
#Injectable({
providedIn: 'root',
})
export class SharedService {
constructor() { }
sharedFunction(){
console.log('here');
}
}
And in both of components, component1:
import { SharedService } from '../shared.service';
import { Component, OnInit } from '#angular/core';
#Component({
selector: '.....',
templateUrl: '.......',
styleUrls: ['........']
})
export class Component1 implements OnInit{
constructor(private sharedService: SharedService) { }
ngOnInit() {
this.sharedService.sharedFunction();
}
}
component2:
import { SharedService } from '../shared.service';
import { Component, OnInit } from '#angular/core';
#Component({
selector: '.....',
templateUrl: '.......',
styleUrls: ['........']
})
export class Component2 implements OnInit{
constructor(private sharedService: SharedService) { }
ngOnInit() {
this.sharedService.sharedFunction();
}
}
Could be done using a service. For illustration purpose let's call it HeaderAndSidebarService:
Filename: header-and-sidebar.service.ts
#import { Injectable } from "#angular/core";
#Injectable()
export class HeaderAndSideBarService {
public testFunction() {
console.log('value');
}
}
To use the service, provide it within both header and sidebar component:
import { Component, OnInit, Input,ViewChild } from '#angular/core';
import { HeaderAndSideBarService } from "./header-and-sidebar.service";
#Component({
...,
providers: [HeaderAndSideBarService]
})
export class HeaderComponent {
constructor(private service: HeaderAndSideBarService ) { }
ngOnInit() {
this.service.testFunction();
}
}

Run function on component display

I want to run a function inside component every time user switch to this component. I tried to use ngOninit (run function inside only once) and other methods like ngOnComponentInit etc. but none of these worked for me.
Maybe I want to do this in a wrong way...
Please advice.
edit:
some example code.
home.component.ts
import { Component, OnInit } from '#angular/core';
import { AuthService } from '../auth/auth.service';
import { Router } from '#angular/router';
#Component({
selector: 'app-home',
templateUrl: './home.component.html',
styleUrls: ['./home.component.css']
})
export class HomeComponent implements OnInit {
constructor(private auth: AuthService, private router: Router) {}
ngOnInit() {
if(this.auth.token == null){
this.router.navigate((['/']));
}
}
someFunction(){
console.log("ok");
}
}
I want to run someFunction() everytime user switch to this component.
Do you mean onFocus()? This is what gets called when a user clicks on or tabs into a component.

Angular2 - Trying to add a component into a child component from parent

I am trying to add component dynamically into a child component from the parent component. I have injected the child component so that I can call its method in order to add component into the child component. Here is how I am doing it:
test.ts
import {Component, DynamicComponentLoader,ElementRef,AfterViewInit} from 'angular2/core';
import {bootstrap} from 'angular2/platform/browser';
import {ChildComponent} from './child_test.ts';
#Component({
selector: 'app',
template: '<div #element></div>',
providers: [ChildComponent,ElementRef]
})
class AppComponent implements AfterViewInit{
constructor(private _loader: DynamicComponentLoader, private _elementRef: ElementRef, private _childComponent: ChildComponent) {
}
ngAfterViewInit(){
this._loader.loadIntoLocation(ChildComponent,this._elementRef,'element');
this._childComponent.addElement();
}
}
bootstrap(AppComponent);
child_test.ts
import {Component, ElementRef,DynamicComponentLoader} from 'angular2/core';
#Component({
selector: 'element',
template: '<div>Test Element</div>'
})
export class MyElement{}
#Component({
selector: "child-component",
template: "<div>Child Component</div>"
})
export class ChildComponent{
constructor(public _elementRef: ElementRef,private _loader: DynamicComponentLoader){}
public addElement(){
this._loader.loadNextToLocation(MyElement,this._elementRef);
}
};
When execute the test.ts I get the following error:
TypeError: Cannot read property 'getViewContainerRef' of undefined
Not sure if I fully understand your question but I think this is what you want
ngAfterViewInit(){
this._loader.loadIntoLocation(ChildComponent,this._elementRef,'element')
.then(childComponent => childComponent.instance.addElement());
}
this._loader.loadIntoLocation(...) returns a Promise that completes with a reference to the added element.

Categories

Resources