Angular: Fill Dropdown with Database - html

I'm new in coding and wanted to make a small Raid Planner.
Now I try to fill my Dropdown with the Raidnames from my database and could need some help with this step. I have problems with adding the data in a dropdownlist.
raid.service.ts
import { HttpClient } from '#angular/common/http';
import { Observable } from 'rxjs';
import { RaidItem } from 'src/app/classes/raid-item';
import { environment } from './../environments/environment';
import { publishReplay, refCount } from 'rxjs/operators';
#Injectable({
providedIn: 'root'
})
export class RaidService {
constructor(private httpClient: HttpClient) { }
private raidApiUrl = environment.webApiBaseUrl + '/api/Raid/';
getRaids(): Observable < RaidItem[] > {
return this.httpClient.get < RaidItem[] > (this.raidApiUrl + 'GetRaids').pipe(
publishReplay(1),
refCount());
}
}
raid.item.ts
export class RaidItem {
Id: number;
Name: string;
}
edit.component.ts
import { Component, OnInit } from '#angular/core';
import { NgbDateStruct, NgbCalendar } from '#ng-bootstrap/ng-bootstrap';
import { NgbDateStructAdapter } from '#ng-bootstrap/ng-bootstrap/datepicker/adapters/ngb-date-adapter';
import { NgbTimeStruct } from '#ng-bootstrap/ng-bootstrap';
import { RaidService } from 'src/services/raid.service';
import { RaidItem } from '../classes/raid-item';
#Component({
selector: 'app-edit',
templateUrl: './edit.component.html',
styleUrls: ['./edit.component.css']
})
export class EditComponent implements OnInit {
time = {hour: 13, minute: 30, second: 0};
hourStep = 1;
minuteStep = 15;
model: NgbDateStruct;
date: {year: number, month: number};
raidItems: RaidItem[] = [];
constructor(private calendar: NgbCalendar, private raidService: RaidService) { }
ngOnInit() {
this.raidService.getRaids().subscribe(raidResult => {
this.raidItems = raidResult;
});
}
selectToday() {
this.model = this.calendar.getToday();
}
onSubmit() {
}
}
edit.component.html
With this step I have the most problems. Don't know exactly how to get the raidnames into the dropdown
<div class="container1">
<ngb-datepicker #dp [(ngModel)]="model" (navigate)="date = $event.next"></ngb-datepicker>
</div>
<div class="container2">
<ngb-timepicker [(ngModel)]="time" [seconds]="false"
[hourStep]="hourStep" [minuteStep]="minuteStep" [secondStep]="00"></ngb-timepicker>
</div>
<select formControlName="raids" id="raids">
<option *ngFor="let RaidItem of getRaids(); let i = index" [value]="getRaids[i].Name">
{{getRaids[i].Name}}
</option>
</select>

You already stored your output in raidItems inside the compoent. SO don't need to call function from template. Use variable to construct the loop.
<option *ngFor="let raidItem of raidItems" [value]="raidItem.Name">
{{raidItem.Name}}
</option>

NgFor already provides alias to each iteration, which in your case is RaidItem. getRaids is a method, but you tried to use it like a variable.
This should work:
<select formControlName="raids" id="raids">
<option *ngFor="let RaidItem of getRaids(); let i = index" [value]="RaidItem.Id">
{{RaidItem.Name}}
</option>
</select>

Related

Angular service not passing form data after routing

New to Angular and I feel like there's just an obvious mistake I am missing, code-wise.
I'm trying to follow the tutorial here: https://youtu.be/CUAHJxWGia0
I have one component to create/add an employee's ID called CreateEmployee.
On submission, it should route to a component to list all employees (ListEmployees).
It's using employee.service.ts.
When I click submit (before or without routing), it correctly logs the employee input to the console on CreateEmployee.
The problem is that when routing to the second component, ListEmployees, my new entry is not displayed at all, and only my test data is displayed.
I've made sure EmployeeService is included in my app.module as well.
create-employee.ts:
import { Component, OnInit } from '#angular/core'
import { FormControl, FormBuilder, NgForm } from '#angular/forms'
import { EmployeeService } from 'app/services/employee.service'
import { Router } from '#angular/router'
import { Employee } from 'app/shared/employee.model'
#Component({
selector: 'app-create-employee',
template: ` <form class="" [formGroup]="employeeForm" (ngSubmit)="saveEmployee()">
<div class="form-control">
<app-input
#memberID
name="memberID"
label="Member ID"
formControlName="memberID"
placeholder="Member ID"
></app-input>
</div>
<div><button type="submit" class="">Save</button></div>
</form>
{{ employeeForm.value | json }}
`,
styleUrls: ['./create-employee.component.scss'],
})
export class CreateEmployeeComponent implements OnInit {
employeeForm: any
constructor(private fb: FormBuilder, private _employeeService: EmployeeService, private _router: Router) {}
employee: Employee = {
memberID: null,
}
ngOnInit(): void {
this.employeeForm = this.fb.group({
memberID: new FormControl(''),
})
this.employee = this.employeeForm.get('memberID').value
}
saveEmployee() {
this._employeeService.save(this.employee)
console.log(this.employeeForm.get('memberID').value)
// this._router.navigate(['employee-list'])
}
}
list-employee.ts
import { Component, OnInit } from '#angular/core'
import { Employee } from 'app/shared/employee.model'
import { EmployeeService } from 'app/services/employee.service'
#Component({
selector: 'app-list-employees',
template: `<div *ngFor="let employee of employees">
<div class="">
{{ employee.memberID }}
</div>
</div> `,
styleUrls: ['./list-employees.component.scss'],
})
export class ListEmployeesComponent implements OnInit {
employees: Employee[] = []
constructor(private _employeeService: EmployeeService) {}
ngOnInit(): void {
this.employees = this._employeeService.getEmployees()
}
}
employee.service.ts
import { Injectable } from '#angular/core'
import { Employee } from 'app/shared/employee.model'
#Injectable({
providedIn: 'root',
})
export class EmployeeService {
listEmployees: Employee[] = [{ memberID: '1' }, { memberID: '2' }]
constructor() {}
getEmployees(): Employee[] {
return this.listEmployees
}
save(employee: Employee) {
this.listEmployees.push(employee)
}
}

Angular, Displays a list multiple times on the same html page, that is updated each round of the loop through c#

I want to display a list as the options in select when in each round in the loop the list will be updated according to the current div
It works in terms of concept, but the html is updated only once according to the last entry in the list and does not display a different list for each loop rotation
my html
<div *ngFor="let item of listConstraint" [value]="item.id">
<p>{{item.name_constraint}}</p>
<select>
<option *ngFor="let item1 of listConstraintDetails" [value]="item1.id">
{{item1.name_constraint}}</option>
</select>
</div>
my ts
import { Component, OnInit } from '#angular/core';
import { FormGroup, FormControl, Validators } from '#angular/forms';
import { Router } from '#angular/router';
import { HttpClient } from '#angular/common/http';
import { AjaxRequestService } from 'src/app/services/Request/ajax-request.service';
import { ConstraintKind } from 'src/app/class/constraintKind';
import { ConstraintDetails } from 'src/app/class/constraint-details';
#Component({
selector: 'app-constraints',
templateUrl: './constraints.component.html',
styleUrls: ['./constraints.component.css']
})
export class ConstraintsComponent implements OnInit {
constraintForm: FormGroup;
listConstraint: ConstraintKind[] = [];
listConstraintDetails: ConstraintDetails[] = [];
constructor(private http: AjaxRequestService, private httpClient: HttpClient, private route: Router) {
}
ngOnInit(): void {
this.GetConstraintsKind();
}
GetConstraintsKind() {
return this.http.GetConstraintsKind().subscribe(data => {
this.listConstraint = data;
data.forEach(element => {
this.GetConstraintsDetails(element.id);
})
console.log(data);
})
}
GetConstraintsDetails(constraintId) {
return this.http.GetConstraintsDetails(constraintId).subscribe(data => {
this.listConstraintDetails = data;
console.log(data);
})
}
}
my functions ajax service
GetConstraintsKind() {
return this.http.get<any>('http://localhost:11818/Api/Constraint/getConstraintKind', { headers: this.header });
}
GetConstraintsDetails(constraintId: number) {
return this.http.get<ConstraintDetails[]>('http://localhost:11818/Api/Constraint/GetConstraintsDetails/' + constraintId);
}
the server works well, and send the correct data, but the html display the same list the whole time
Thanks so much for any help
You are performing inner loop operation all at ngOnInit inside a single array, thats overwriting previously fetched data in the listConstraintDetails array.
What you want can be achieved, if you modify your code a little, like this
ngOnInit(): void {
this.GetConstraintsKind();
}
GetConstraintsKind() {
return this.http.GetConstraintsKind().subscribe(data => {
this.listConstraint = data;
})
}
GetConstraintsDetails(constraintId):ConstraintDetails[]{
let itemsarr: ConstraintDetails[] = [];
if(constraintId)
{
this.http.GetConstraintsDetails(constraintId).subscribe(data => {
itemsarr = data;
})
}
return itemsarr;
}
And your html would get modified like
<div *ngFor="let item of listConstraint" [value]="item.id">
<p>{{item.name_constraint}}</p>
<select>
<option *ngFor="let item1 of GetConstraintsDetails(item.id)" [value]="item1.id">
{{item1.name_constraint}}</option>
</select>
</div>
Thanks.
my html
<div *ngFor="let item of listConstraint" [attr.data-value]="item.id">
<p>{{item.name_constraint}}</p>
<select *ngIf="constraintDetails[item.id]">
<option *ngFor="let item1 of constraintDetails[item.id]" [value]="item1.id">
{{item1.name_constraint}}</option>
</select>
</div>
my ts
import { Component, OnInit } from '#angular/core';
import { FormGroup, FormControl, Validators } from '#angular/forms';
import { Router } from '#angular/router';
import { HttpClient } from '#angular/common/http';
import { AjaxRequestService } from 'src/app/services/Request/ajax-request.service';
import { ConstraintKind } from 'src/app/class/constraintKind';
import { ConstraintDetails } from 'src/app/class/constraint-details';
import { Observable } from 'rxjs';
#Component({
selector: 'app-constraints',
templateUrl: './constraints.component.html',
styleUrls: ['./constraints.component.css']
})
export class ConstraintsComponent implements OnInit {
constraintForm: FormGroup;
listConstraint: ConstraintKind[] = [];
listConstraintDetails: ConstraintDetails[] = [];
constraintDetails = {};
constructor(private http: AjaxRequestService, private httpClient: HttpClient, private route: Router) {
}
ngOnInit(): void {
this.GetConstraintsKind();
}
GetConstraintsKind() {
return this.http.GetConstraintsKind().subscribe(data => {
this.listConstraint = data;
for (let i = 0; i < this.listConstraint.length; i++) {
const element = this.listConstraint[i].id;
this.http.GetConstraintsDetails(element)
.subscribe(cd => {
this.constraintDetails[element] = cd;
console.log(this.constraintDetails)
});
}
})
}
GetConstraintsDetails(constraintId): ConstraintDetails[] {
console.log(constraintId);
let itemsarr: ConstraintDetails[] = [];
if (!itemsarr) {
this.http.GetConstraintsDetails(constraintId).subscribe(data => {
itemsarr = data;
})
}
return itemsarr;
}
}

InvalidPipeArgument: '[object Object]' for pipe 'AsyncPipe' at invalidPipeArgumentError

I want to get some data from database
Here is my service
export class CategoryService {
constructor(private db: AngularFireDatabase) { }
getCategories(){
return this.db.list('/categories');
}
$Component code
export class ProductFormComponent implements OnInit {
categories$;
constructor(categoryService: CategoryService) {
this.categories$ = categoryService.getCategories();
}
$here is my html
<div class="form-group">
<label for="category">Category</label>
<select id="category" class="form-control">
<option value=""> </option>
<option *ngFor="let c of categories$ | async" [value]="c.$key">
{{c.name}}
</option>
</select>
</div>
Firebase libraries return promises. Make them return observables.
import { from } from 'rxjs/operators';
export class CategoryService {
constructor(private db: AngularFireDatabase) { }
getCategories(){
return from(this.db.list('/categories'));
}
Try these code it should work
import {Injectable} from '#angular/core';
import {AngularFireDatabase} from '#angular/fire/database';
import {from} from 'rxjs';
#Injectable({
providedIn: 'root'
})
export class CategoryService {
constructor(private db: AngularFireDatabase) {}
getCategories() {
return from(this.db.list('/categories').valueChanges());
}
}

Firebase Cloud Firestore can not load data

When I open web data is show but I change component and come back this component data not show.It show no item. I check log but not run to ngOnIt. ngOnIt run on web strat or web reload.
this is stock.service.ts
import { Injectable } from '#angular/core';
import { AngularFirestore, AngularFirestoreCollection, AngularFirestoreDocument } from 'angularfire2/firestore';
import { Observable } from 'rxjs/Observable';
import { Stock } from './stock.model';
#Injectable()
export class StockService {
stocksCollection: AngularFirestoreCollection<Stock>;
stocks: Observable<Stock[]>;
constructor(public afs: AngularFirestore) {
this.stocks = this.afs.collection('stocks').valueChanges();
}
getStock(){
return this.stocks;
}
}
stock.component.ts
import { Component, OnInit, Input } from '#angular/core';
import { ActivatedRoute,Params } from '#angular/router';
import { StockService } from '../shared/stock.service';
import { Stock } from '../shared/stock.model';
import { Brands } from '../shared/brand';
import { Subscription } from 'rxjs/Subscription';
#Component({
selector: 'app-stock',
templateUrl: './stock.component.html',
styleUrls: ['./stock.component.css']
})
export class StockComponent implements OnInit {
stocks: Stock[];
brand: Brands;
sub: Subscription;
brand_name: string;
constructor(
private stockService: StockService,
private router: ActivatedRoute
) { }
ngOnInit() {
this.stockService.getStock().subscribe(stocks => {
console.log(stocks);
this.stocks = stocks;
});
this.sub = this.router.params.subscribe(params =>{
this.brand_name = params['brand'];
});
console.log('Brand : '+this.brand_name);
}
}
and stock.component.html
<div *ngIf="stocks != null || stocks?.length > 0 ; else noStocks" >
<ul *ngFor="let item of stocks" class="collection">
<li class="collection-item " >{{item.name}} | {{item.brand}} | {{item.price}}</li>
</ul>
</div>
<ng-template #noStocks>
<p>no item</p>
</ng-template>
I don't know where code is mistake. Thank you for answer.
Don't load inside the constructor of your service, move it inside your method
constructor(public afs: AngularFirestore) {
}
getStock(){
this.stocks = this.afs.collection('stocks').valueChanges();
return this.stocks;
}

Retaining selected option from dropdown

i have a dropdown with different options. i want to keep the selected option at the top of the dropdown till the user changes it. Right now if i select any options and i go out of the component and then come back, the dropdown reset with the first value....
HTML
<select class="form-control-mb-12"
(change)="intSelection($event.target.value)" >
<option value="1/4">1/4</option>
<option value="1/8">1/8</option>
<option value="1/16">1/16</option>
<option value="1/32">1/32</option>
</select>
Component
import { Component, OnInit } from '#angular/core';
import {NgbModal, ModalDismissReasons} from '#ng-bootstrap/ng-bootstrap';
import { ModuladorService } from 'app/Services/modulador.service'
#Component({
selector: 'app-resumen',
templateUrl: './resumen.component.html',
styleUrls: ['./resumen.component.scss'],
providers: [ModuladorService]
})
export class ResumenComponent implements OnInit {
intSelected : string = "" ;
constructor(private _moduladorService:ModuladorService) {
this.intSelected = this._moduladorService.obtenerParametros();
}
ngOnInit() {
}
intSelection(value){
switch(value) {
case "1/4":
this.intSelected = value;
break;
case "1/8":
this.intSelected = value;
break;
case "1/16":
this.intSelected = value;
break;
case "1/32":
this.intSelected = value;
break;
}
this._moduladorService.actualizarParametros(this.intSelected);
}
SERVICE
import { Injectable } from '#angular/core';
import { InitParam } from 'app/layout/modulador/resumen/init-param'
#Injectable()
export class ModuladorService extends InitParam {
constructor() {
super();
this.load();
}
obtenerParametros(){
var intSelected = JSON.parse(localStorage.getItem('intSelected'));
return intSelected;
}
actualizarParametros(newParam : any){
var intSelected = JSON.parse(localStorage.getItem('intSelected'));
intSelected = newParam;
localStorage.setItem('intSelected', JSON.stringify(intSelected));
}
}
iNIT FOR SERVICE
export class InitParam {
load(){
if(localStorage.getItem('intSelected')=== null ){
console.log('No se encontraron parametros...');
var intSelected = '1/4'
localStorage.setItem('intSelected', JSON.stringify(intSelected));
}else{
console.log('Cargando parametros...');
}
}
}
You could keep the selected things in an #Injectable service, which, if not made as, definitely feels like, a singleton.
Or input / output it from / to a parent component.
You need storage data in services. Services injectable to module.
If you need save information in all application - use services in providers at app.module.ts