Add Select inside Angular FormGroup and bind selected value - javascript

I have a form with a text input and then I want to add a select inside that Form:
The select is an array:
typeAlert: TypeAlert[] = [
{ value: 'MEDICAL'},
{ value: 'POLICE'},
{ value: 'FIRE'}
];
I want to bind the value selected on the select. I have a var called select to store which the user has selected. I have to add the selected inside formGroup?
Also I am getting this error:
ngModel cannot be used to register form controls with a parent formGroup directive
component.html
<form class="container" [formGroup]="alertForm">
<div class="actions">
<div class="action" [routerLink]="['/alertes']">
<span>Torna a Alertes</span>
</div>
<div class="space"></div>
<button class="action" (click)="save()" [disabled]="!alertForm.valid">
Guardar
</button>
</div>
<div class="dades">
<div class="card">
<div class="card-title">
<b>Title</b>
</div>
<div class="card-content">
<mat-form-field>
<mat-label>Title</mat-label>
<input formControlName="title" matInput>
</mat-form-field>
</div>
</div>
</div>
<div class="dades">
<div class="card">
<div class="card-title">
<b>Type Alert</b>
</div>
<div class="card-content">
<mat-form-field appearance="fill">
<mat-label>Type Alert</mat-label>
<mat-select [(ngModel)]="selected">
<mat-option *ngFor="let alert of typeAlert" [value]="alert.value">
{{alert.value}}
</mat-option>
</mat-select>
</mat-form-field>
</div>
</div>
</div>
</form>
component.ts:
import { Component, OnInit, OnDestroy } from '#angular/core';
import { FormGroup, FormControl, FormArray, Validators } from '#angular/forms';
import { ActivatedRoute, Router } from '#angular/router';
import { AlertesService } from 'src/app/core/services/alertes.service';
import { MatDialog } from '#angular/material/dialog';
import { DialogNotificationsComponent } from 'src/app/shared/components/dialog-notifications/dialog-notifications.component';
interface TypeAlert {
value: string;
}
#Component({
selector: 'app-alert',
templateUrl: './alert.component.html',
styleUrls: ['./alert.component.scss']
})
export class AlertComponent implements OnInit, OnDestroy {
typeAlert: TypeAlert[] = [
{ value: 'MEDICAL'},
{ value: 'POLICE'},
{ value: 'FIRE'}
];
selected: string = this.typeAlert[0].value;
alertForm: FormGroup;
alert;
constructor(
private alertesService: AlertesService,
private route: ActivatedRoute,
private router: Router,
public dialog: MatDialog
) { }
ngOnInit() {
this.alert = this.route.snapshot.data.alert;
this.initForm();
}
ngOnDestroy() {
}
initForm() {
this.alertForm = new FormGroup({
title: new FormControl(this.alert ? this.alert.title : '', [Validators.required]),
});
}
save() {
console.log(this.selected);
if(this.alert) {
this.alertesService.update(this.alert._id, this.alertForm.value).subscribe(() => {
this.router.navigate(['/alertes'])
})
}
else {
const dialogRef = this.dialog.open(DialogNotificationsComponent, {
width: '600px',
data: {title: "Nova alerta", msg: this.alertForm.value.title}
});
dialogRef.afterClosed().subscribe(result => {
console.log(result);
if(result != undefined && result != null) {
this.alertesService.create({
notification: result ? result: null,
...this.alertForm.value
}).subscribe(() => {
this.router.navigate(['/alertes'])
})
}
});
}
}
}

You should [formControlName] with form groups, instead of ngmodel.
Please check https://angular.io/api/forms/FormControlName

Related

i get error Cannot read properties of undefined (reading 'include')

I get this error when i click login button in my login page
: this error is here :
Cannot read properties of undefined (reading 'include') when i call
window.location.reload();
what is the problem, I searched but did not find the problem
I am thankful with your guidance
my ts code is here :
import { Component, OnInit } from '#angular/core';
import { AuthService } from '../_services/auth.service';
import { TokenStorageService } from '../_services/token-storage.service';
#Component({
selector: 'app-login',
templateUrl: './login.component.html',
styleUrls: ['./login.component.css']
})
export class LoginComponent implements OnInit {
form: any = {
username: null,
password: null
};
isLoggedIn = false;
isLoginFailed = false;
errorMessage = '';
roles: string[] = [];
constructor(private authService: AuthService, private tokenStorage: TokenStorageService) { }
ngOnInit(): void {
if (this.tokenStorage.getToken()) {
this.isLoggedIn = true;
this.roles = this.tokenStorage.getUser().roles;
}
}
onSubmit(): void {
const { username, password } = this.form;
this.authService.login(username, password).subscribe(
data => {
this.tokenStorage.saveToken(data.accessToken);
this.tokenStorage.saveUser(data);
this.isLoginFailed = false;
this.isLoggedIn = true;
this.roles = this.tokenStorage.getUser().roles;
this.reloadPage();
},
err => {
this.errorMessage = err.error.message;
this.isLoginFailed = true;
}
);
}
reloadPage(): void {
window.location.reload();
}
}
and my html code is
<div id="image">
<div class="container">
<div class="row justify-content-center">
<div class="col-sm-10 col-md-8 col-lg-6 col-xl-5 p-5 ">
<mat-card>
<mat-card-header >
<mat-card-title> </mat-card-title>
</mat-card-header>
<mat-card-content>
<img src="https://s4.uupload.ir/files/user3_r3fq.png" class="p-2">
<form *ngIf="!isLoggedIn"
name="form"
(ngSubmit)="f.form.valid && onSubmit()"
#f="ngForm"
novalidate
>
<div class="form-group justify-content-center ">
<mat-form-field >
<label for="username"></label>
<i class="fa fa-user icon"></i>
<input matInput
type="text"
name="username"
placeholder="Username"
[(ngModel)]="form.username"
required
#username="ngModel"
/></mat-form-field>
<div id="mes"
role="alert"
*ngIf="username.errors && f.submitted"
>
please enter user name
</div>
</div>
<div class="form-group"> <mat-form-field>
<label for="password"></label>
<input matInput
type="password"
placeholder="Password"
name="password"
[(ngModel)]="form.password"
required
minlength="4"
#password="ngModel"
/>
</mat-form-field>
<div
role="alert"
*ngIf="password.errors && f.submitted"
>
<div id="mes" *ngIf="password.errors.required">Please Enter pass</div>
<div *ngIf="password.errors.minlength">
Password must be at least 6 characters
</div>
</div>
</div>
<div >
<button mat-raised-button class="btn btn-primary" >
<span>Login</span>
</button>
</div>
<div >
<div
role="alert"
*ngIf="f.submitted && isLoginFailed"
>
Login failed: {{ errorMessage }}
</div>
</div>
</form>
</mat-card-content>
</mat-card>
<div *ngIf="isLoggedIn">
Logged in as {{ roles }}.
</div>
</div>
</div>
</div>
</div>
and my user.service.ts is
import { Injectable } from '#angular/core';
import { HttpClient } from '#angular/common/http';
import { Observable } from 'rxjs';
const API_URL = 'http://localhost:8080/api/test/';
#Injectable({
providedIn: 'root'
})
export class UserService {
constructor(private http: HttpClient) { }
getPublicContent(): Observable<any> {
return this.http.get(API_URL + 'all', { responseType: 'text' });
}
getUserBoard(): Observable<any> {
return this.http.get(API_URL + 'user', { responseType: 'text' });
}
getModeratorBoard(): Observable<any> {
return this.http.get(API_URL + 'mod', { responseType: 'text' });
}
getAdminBoard(): Observable<any> {
return this.http.get(API_URL + 'admin', { responseType: 'text' });
}
}
and my auth.service.ts is
import { Injectable } from '#angular/core';
import { HttpClient, HttpHeaders } from '#angular/common/http';
import { Observable } from 'rxjs';
const AUTH_API = 'http://192.168.1.135:8282/api/Users/authenticate';
const httpOptions = {
headers: new HttpHeaders({ 'Content-Type': 'application/json' })
};
#Injectable({
providedIn: 'root'
})
export class AuthService {
m:any;
constructor(private http: HttpClient) { }
login(username: string, password: string): Observable<any> {
this.m= this.http.post(AUTH_API , {username,password}, httpOptions);
console.log(this.m);
return this.m;
}
register(username: string, email: string, password: string): Observable<any> {
return this.http.post(AUTH_API + 'signup', {
username,
email,
password
}, httpOptions);
}
}
Seem you have issues in this line, you need to check if getUser is returning what you need. To suppress the error you need to change:
this.roles = this.tokenStorage.getUser().roles;
Try changing to:
this.roles = this.tokenStorage.getUser()?.roles;

Form control missing randomly for reactive form with filter pipe

Below is a simple reactive form with the filter of an array of checkboxes.
As soon as page render getting error
Cannot find control with path: 'accountsArray -> 555'
However, the filter is working perfectly, but while removing any character from filter throws an error
Cannot find control with path: 'accountsArray -> 123'
Form control not found based on search.
Below is length code, but that will help you to understand clearly.
Component:
import { Component, OnInit } from '#angular/core';
import { FormBuilder, FormArray, FormGroup, FormControl } from '#angular/forms';
import { SubAccount } from './account-model';
#Component({
selector: 'my-app',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent implements OnInit {
searchForm: FormGroup;
searchTerm = '';
formUpdated = false;
accounts = [
new SubAccount('123'),
new SubAccount('555'),
new SubAccount('123555')
];
subAccount = [];
constructor(private fb: FormBuilder) { }
get accountsArray(): FormArray {
return this.searchForm.get('accountsArray') as FormArray;
}
addAccount(theAccount: SubAccount) {
this.accountsArray.push(this.fb.group({
account: theAccount
}));
}
ngOnInit() {
this.formUpdated = false;
this.searchForm = this.fb.group({
accountSearch: '',
accountsArray: this.fb.array([new FormControl('')])
});
this.accounts.forEach((field: any) => {
this.subAccount.push({ key: field.key, value: field.key });
});
const fieldFGs = this.subAccount.map((field) => {
const obj = {};
if (field.value) {
obj[field.value] = true;
} else {
obj[field] = true;
}
return this.fb.group(obj);
});
const fa = this.fb.array(fieldFGs);
this.searchForm.setControl('accountsArray', fa);
this.formUpdated = true;
}
getAccountNumber(account: SubAccount) {
return Object.keys(account)[0];
}
}
View:
<div [formGroup]="searchForm" *ngIf="formUpdated">
<label for="search">Find an account...</label>
<input id="search" formControlName="accountSearch" [(ngModel)]="searchTerm" />
<div formArrayName="accountsArray" *ngIf="formUpdated">
<div *ngFor="let account of accountsArray.controls | filter: 'key' :searchTerm; let ind=index">
<input type="checkbox" id="checkbox_claim_debtor_{{ind}}" formControlName="{{getAccountNumber(account.controls)}}"/>
<span> {{getAccountNumber(account.controls)}} </span>
</div>
</div>
</div>
Pipe:
import { Pipe, PipeTransform } from '#angular/core';
#Pipe({
name: 'filter'
})
export class FilterPipe implements PipeTransform {
transform(items: any[], field: string, value: string): any[] {
if (!value && !items) {
return items;
}
return items.filter((item) => {
const val = Object.keys(item.controls)[0];
if (val && val.toLowerCase().indexOf(value.toLowerCase()) >= 0) {
return true
} else {
return false;
}
});
}
}
Appreciate your help.
Stackblitz link:
https://stackblitz.com/edit/angular-9ouyqr
please check the [formGroupName]="ind" , it is not written while iterating the form array ,formGroupname should be addeed with the form index
<div [formGroup]="searchForm" *ngIf="formUpdated">
<label for="search">Find an account...</label>
<input id="search" formControlName="accountSearch" [(ngModel)]="searchTerm" />
<div formArrayName="accountsArray" *ngIf="formUpdated">
<div [formGroupName]="ind" *ngFor="let account of accountsArray.controls | filter: 'key' :searchTerm; let ind=index"
>
<input type="checkbox" id="checkbox_claim_debtor_{{ind}}" formControlName="{{getAccountNumber(account.controls)}}"/>
<span> {{getAccountNumber(account.controls)}} </span>
</div>
</div>
</div>

Accessing ControlValueAccessor from different component

I have component where I implement ControlValueAccessor and I'm having problems understanding the correct way to use it:
import { Component, OnInit, forwardRef, Output, EventEmitter, OnChanges, Input, ViewChild } from '#angular/core';
import { NG_VALUE_ACCESSOR, ControlValueAccessor } from '#angular/forms';
import { UserOrEmail } from '../entities/UserOrEmail';
export const USER_INPUT_CONTROL_VALUE_ACCESSOR: any = {
provide: NG_VALUE_ACCESSOR,
// tslint:disable-next-line
useExisting: forwardRef(() => AddUserOrEmailComponent),
multi: true,
};
const noop = () => {
// Placeholder operation
};
#Component({
selector: 'app-add-user-or-email',
templateUrl: './add-user-or-email.component.html',
providers: [USER_INPUT_CONTROL_VALUE_ACCESSOR]
})
export class AddUserOrEmailComponent implements OnInit, ControlValueAccessor {
#Input()
user: any = UserOrEmail;
#Output()
change: EventEmitter<UserOrEmail> = new EventEmitter<UserOrEmail>();
users: any = [];
ngOnInit() {
this.user = {
userId: 'ull',
name: 'null',
email: 'null'
};
this.users = ConstantService.UserArray;
}
// #region [ Value Accessor Interface ]--------------------------------------------------------
// Placeholders for the callbacks which are later provided
// by the Control Value Accessor
private onTouchedCallback: () => void = noop;
private onChangeCallback: (_: any) => void = noop;
get value(): any {
return this.user;
}
// [ ControlValueAccessor interface implementation ]-------------------------------------------
set value(v: any) {
if (this.user !== v) {
this.user = <UserOrEmail>v;
this.onChangeCallback(v);
this.change.next(this.user);
}
}
writeValue(value: any) {
if (value !== this.user)
this.user = <UserOrEmail>value;
}
registerOnChange(fn: any) {
this.onChangeCallback = fn;
}
registerOnTouched(fn: any) {
this.onTouchedCallback = fn;
}
}
and html:
<div>
<div class="form-column">
<div class="form-row">
<label>
{{'GENERIC.USER'|translate}}
</label>
<select>
<option [ngValue]="'default'"></option>
<option *ngFor="let user of users" [ngValue]="user">{{user.login}}</option>
</select>
</div>
<div class="form-row">
<label for="addPersonEmail" >{{'GENERIC.EMAIL' | translate}}</label>
<input type="email" placeholder="{{'GENERIC.EMAIL'|translate}}" pattern="^\w+([\.-]?\w+)*#\w+([\.-]?\w+)*(\.\w{2,3})+$">
</div>
</div>
</div>
I try to use it in another component:
hmtl:
<app-modal class="form" #addMilestoneModal [width]="550">
<div header>{{'MODALS.ADD_MILESTONE'|translate}}</div>
<div body>
<div class="form-column">
<div class="form-value">
<app-add-user-or-email #addUser [(ngModel)]="milestone.assignee"></app-add-user-or-email>
</div>
<div class="form-row">
<label for="addMilestoneDescription">{{'GENERIC.DESCRIPTION' | translate}}</label>
<textarea style="height: 150px" [(ngModel)]="milestone.description"></textarea>
</div>
</div>
</div>
<div footer class="flex-container">
<button class="flex-item-row btn btn-a" [disabled]="!milestone.description" (click)="apply()">{{'GENERIC.APPLY'
| translate}}</button>
</div>
</app-modal>
Typescript:
import { Component, ViewChild, EventEmitter } from '#angular/core';
import { ModalComponent } from '../../widgets/modal/modal.component';
import { Milestone } from '../../entities/Milestone';
import { ConstantService } from '../../services/ConstantService';
import { AddUserOrEmailComponent } from '../../add-user-or-email/add-user-or-email.component';
#Component({
selector: 'app-add-milestone-modal',
templateUrl: './add-milestone-modal.component.html'
})
export class AddMilestoneModalComponent {
#ViewChild('addMilestoneModal')
modal: ModalComponent;
cs = ConstantService;
emitter: EventEmitter<Milestone> = new EventEmitter<Milestone>();
milestone: any = Milestone;
apply() {
console.log(this.milestone); // <---- HERE IT SHOULD BE ACCESSED
debugger;
this.emitter.next(this.milestone);
this.modal.close();
}
cancel() {
this.emitter.next(null);
this.modal.close();
}
}
I should get it in milestone object but it is empty. What am I missing?
I had problems with this a couple of weeks ago and made a StackBlitz with a good example.
Hopefully this can help you?
https://stackblitz.com/edit/mat-select-with-controlvalueaccessor

how to hide a form in angular

I have been trying to hide my form and making it appear only when user click on the button. but for some reason, the function I have created never work is there something wrong with my code? and I saw quite a few example that uses angular.module and I tried it but I always get an error message.
transfer.component.html
<form [formGroup]="AddRiciverForm" id="AddRiciverForm" (ngSubmit)="addRiciverFunc()" *ngIf="show">
<div class="container">
<div class="row">
<div class="col-sm-6 col-sm-offset-3">
<p><input type="email" id="emailTo" formControlName="emailTo" placeholder="Reciver Email" [(ngModel)]="this.AddRiciverForm.value.emailTo" required></p>
</div>
</div>
<div class="row">
<div class="col-sm-6 col-sm-offset-3">
<p><button class="btn btn-primary" type="submit" [disabled]="!transferForm.form.valid">Add</button> </p>
</div>
</div>
</div>
</form>
<button ng-click="AddEmailFunc()">add user</button>
transfer.component.ts
import { Component, OnInit } from '#angular/core';
import { AuthService } from '../auth.service';
import { FormBuilder, FormGroup } from '#angular/forms';
import { Router } from '#angular/router';
import { Http } from '#angular/http';
import { PostsService } from '../posts.service';
#Component({
selector: 'app-transfer',
templateUrl: './transfer.component.html',
styleUrls: ['./transfer.component.css']
})
export class TransferComponent implements OnInit {
constructor(private fb: FormBuilder, private http: Http, private router: Router, private auth: AuthService,private postsService: PostsService) { }
transfer = {};
addRiciver = {};
recivers: any;
AddRiciverForm: FormGroup;
transferForm: FormGroup;
public userEmail: string;
show=false;
ngOnInit() {
this.transferForm = this.fb.group({
emailTo: '',
amount: ''
});
this.AddRiciverForm = this.fb.group({
emailTo: ''
});
this.auth.currentEmail.subscribe(email => this.userEmail = email);
this.postsService.getAllReciver().subscribe(reciver => {
this.recivers = reciver;
});
}
transFunds(){
}
addRiciverFunc(){
this.addRiciver={
emailFrom: this.userEmail,
emailTo: this.AddRiciverForm.value.emailTo
}
this.http.post('/transfer', this.addRiciver)
.subscribe(res => {
let id = res['_id'];
}, (err) => {
console.log(err);
}
);
}
AddEmailFunc(){
if(!this.show){
this.show = true;
}
}
}
You must try adding [hidden]="AddEmailFunc()" on your form.
please see my sample code
import { Component } from '#angular/core';
#Component({
selector: 'Sandbox',
template: `<form [hidden]="isDisplayed">
<label>Sample: </label>
<input type="text">
</form>
<button (click)="showMe()">Click</button>`
})
export class SandboxComponent{
isDisplayed = true;
showMe()
{
if(this.isDisplayed)
{
this.isDisplayed = false;
}else{
this.isDisplayed = true;
}
}
}
Hope it helps. :) cheers!
You are mixing angularjs (1.x) and angular (>2)
the ng-click in Angular should be:
<button (click)="AddEmailFunc()">add user</button>
If this does not solve your issue please post the full component.
you can use *ngIf in and (model) binded to event click of button.
<button (click)="changeView()">add user</button>
and clickEvent
changeView(){
this.showForm = !this.showForm;
}

Angular 2 Inline template cannot read property of undefined

I am trying to render data inside a tab body section based on clicking an icon on a tabset. Here is a screen shot of my initial, successfully rendered view:
But when I click a new tabset icon to load data into the tab body section, I get the following exception:
TypeError: Cannot read property 'category' of undefined
at CompiledTemplate.proxyViewClass.View_DnDMiniCardGroupComponent0.detectChangesInternal (/PaletteSchemaModule/DnDMiniCardGroupComponent/component.ngfactory.js:144)
at CompiledTemplate.proxyViewClass.AppView.detectChanges (view.js:425)
at CompiledTemplate.proxyViewClass.DebugAppView.detectChanges (view.js:620)
at CompiledTemplate.proxyViewClass.AppView.internalDetectChanges (view.js:410)
at CompiledTemplate.proxyViewClass.View_TabCommunityComponent0.detectChangesInternal (/PaletteSchemaModule/TabCommunityComponent/component.ngfactory.js:89)
at CompiledTemplate.proxyViewClass.AppView.detectChanges (view.js:425)
at CompiledTemplate.proxyViewClass.DebugAppView.detectChanges (view.js:620)
at CompiledTemplate.proxyViewClass.AppView.internalDetectChanges (view.js:410)
at View_TypesContentComponent2.detectChangesInternal (/PaletteSchemaModule/TypesContentComponent/component.ngfactory.js:190)
at View_TypesContentComponent2.AppView.detectChanges (view.js:425)
at View_TypesContentComponent2.DebugAppView.detectChanges (view.js:620)
at ViewContainer.detectChangesInNestedViews (view_container.js:67)
at CompiledTemplate.proxyViewClass.View_TypesContentComponent0.detectChangesInternal (/PaletteSchemaModule/TypesContentComponent/component.ngfactory.js:592)
at CompiledTemplate.proxyViewClass.AppView.detectChanges (view.js:425)
at CompiledTemplate.proxyViewClass.DebugAppView.detectChanges (view.js:620)
Here is a slice of my tabset template that shows tab content body based on ngSwitch and ngSwitchCase:
<div class="schema-palette" [ngSwitch]="tabId">
<myapp-base-palette *ngSwitchCase="'T'">
<myapp-tabset [tabType]="'T'" (onTabSelected)="tabChanged($event)" palette-tabset></myapp-tabset>
<myapp-tab-community palette-content-region></myapp-tab-community>
</myapp-base-palette>
</div>
Here is my myapp-tab-community component template:
<div class="community-buffer" ngFor="let miniCardGrp of miniCardGrps; let i = index">
<div style="height:5px" *ngIf="i === 0"></div>
<myapp-dnd-mini-card-group [miniCardGrp]="miniCardGrp"></myapp-dnd-mini-card-group>
</div>
Here is myapp-tab-community component typescript:
import { Component, OnInit, AfterViewInit } from '#angular/core';
import { PalettesService } from '../../palettes.service';
import { MiniCardGroup } from '../../palettes.helpers';
import { DnDMiniCardGroupComponent } from '../../shared/dnd-mini-card-group/dnd-mini-card-group.component';
#Component({
selector: 'myapp-tab-community',
templateUrl: './tab-community.component.html',
styleUrls: ['./tab-community.component.scss'],
providers: [PalettesService]
})
export class TabCommunityComponent implements OnInit, AfterViewInit {
miniCardGrps: MiniCardGroup[];
constructor(private palettesService: PalettesService) {}
ngOnInit() {
this.miniCardGrps = [];
this.miniCardGrps = this.palettesService.getTemplateTypes();
// DATA IS SUCCESSFULLY RETRIEVED
console.log('TabCommunityComponent.ngOnInit = ' + JSON.stringify(this.miniCardGrps));
}
ngAfterViewInit() {
// ERROR BLOCKS EVALUATION
console.log('TabCommunityComponent.ngAfterViewInit = ' + JSON.stringify(this.miniCardGrps));
}
trackByMiniCardGroup(index: number, miniCardGrp: MiniCardGroup) {
return miniCardGrp.category;
}
}
An array of myapp-dnd-mini-card-group components should be rendered but the error is thrown from its template.
The template file:
<div class="mini-card-grp-collapse">
<div class="mini-card-grp-collapse-row">
<div class="mini-card-grp-title">
<a data-toggle="collapse" [href]="href" aria-expanded="true" attr.aria-controls="{{ ariaControls }}">
<!-- THIS LINE THROWS -->
<md-icon class="white-text md-16">play_arrow</md-icon>{{ miniCardGrp.category }}
</a>
</div>
<div class="mini-card-grp-title-helper">
<md-icon class="white-text md-24">help_outline</md-icon>
</div>
</div>
</div>
<div class="collapse in" [id]="id">
<div class="mini-card-wrapper" *ngFor="let miniCard of miniCardGrp.miniCards">
<myapp-dnd-mini-card [miniCard]="miniCard"></myapp-dnd-mini-card>
</div>
</div>
Now the typescript file:
import { Component, OnInit, AfterViewInit, Input } from '#angular/core';
import { MathHelper } from '../../../../utils/math';
import { MiniCardGroup } from '../../palettes.helpers';
import { DndMiniCardComponent } from '../dnd-mini-card/dnd-mini-card.component';
#Component({
selector: 'myapp-dnd-mini-card-group',
templateUrl: './dnd-mini-card-group.component.html',
styleUrls: ['./dnd-mini-card-group.component.scss']
})
export class DnDMiniCardGroupComponent implements OnInit, AfterViewInit
{
#Input() miniCardGrp: MiniCardGroup;
#Input() href: string;
#Input() id: string;
#Input() ariaControls: string;
constructor() {
let mathHelper = new MathHelper();
let random$ = mathHelper.getRandomNumberString();
this.id = random$;
this.href = '#' + random$;
this.ariaControls = random$;
}
ngOnInit() {
// IS UNDEFINED
console.log('DnDMiniCardGroupComponent.ngOnInit = ' + JSON.stringify(this.miniCardGrp));
}
ngAfterViewInit() {
// IS NEVER REACHED
console.log('DnDMiniCardGroupComponent.ngAfterViewInit = ' + JSON.stringify(this.miniCardGrp));
}
}
What am I doing wrong here?
As requested, here is what the mini-card-group component looks like:
<div class="btn-grp-collapse">
<div class="btn-grp-collapse-row">
<div class="btn-grp-title">
<a data-toggle="collapse" [href]="href" aria-expanded="true" attr.aria-controls="{{ ariaControls }}">
<md-icon class="white-text md-16">play_arrow</md-icon>{{ dndButtonGrp.title }}
</a>
</div>
<div class="btn-grp-title-helper">
<md-icon class="white-text md-24">help_outline</md-icon>
</div>
</div>
</div>
<div class="collapse in" [id]="id">
<div class="btn-wrapper" *ngFor="let dndButton of dndButtonGrp.dndButtons">
<myapp-dnd-button [dndButton]="dndButton"></myapp-dnd-button>
</div>
</div>
Its typescript file:
import { Component, Input, OnInit } from '#angular/core';
import { MathHelper } from '../../../../utils/math'
import { DnDButtonGroup } from './dnd-button-group.helpers';
import { DndButtonComponent } from '../dnd-button/dnd-button.component';
#Component({
selector: 'myapp-dnd-button-group',
templateUrl: './dnd-button-group.component.html',
styleUrls: ['./dnd-button-group.component.scss']
})
export class DnDButtonGroupComponent implements OnInit {
#Input() dndButtonGrp: DnDButtonGroup;
#Input() href: string;
#Input() id: string;
#Input() ariaControls: string;
constructor() {
let mathHelper = new MathHelper();
let random$ = mathHelper.getRandomNumberString();
this.id = random$;
this.href = '#' + random$;
this.ariaControls = random$;
}
ngOnInit() {}
}
When you call the service the data might not be arrived yet, you need to subscribe to the service to get the data
ngOnInit() {
this.palettesService
.getTemplateTypes()
.subscribe(data => this.miniCardGrps = data);
}
I needed to implement dynamic components to render content for each tab. Here is the relevant link for a full background:
https://angular.io/docs/ts/latest/cookbook/dynamic-component-loader.html

Categories