I trying to populate a dropdown with my firebase data. I am using angular 9.1.9. Please assist.
category.service.ts
constructor(private db: AngularFireDatabase) { }
getCategories() {
return this.db.list('/categories', (ref) => ref.orderByChild('name'))
.snapshotChanges()
.pipe(
map((actions) => {
return actions.map((action) => ({
key: action.key,
val: action.payload.val(),
}));
})
);
}
product-form.component.html
<select [ngModel] id="category" class="form-control">
<option value=""></option>
<option *ngFor="let c of categories$ | async" [value]="c.key">
{{c.payload.val().name}}
</option>
</select>
products-form-component.ts
export class ProductFormComponent implements OnInit {
categories$;
constructor(categoryService: CategoryService) {
this.categories$ = categoryService.getCategories();
}
{{c.val.name}} would help as your val object already contained payload.val(), just need to access name property from it.
Related
I am trying to populate a dropdown by accessing an array property from the class which is wrapped inside an observable.
I have an interface like below :
export interface IApplicationConfigurationResponse
{
settings?: Settings[] ] undefined;
}
export class ApplicationConfigurationResponse
{
settings?: Settings[] ] undefined;
}
export class Settings
{
settingId!:number;
name!:string;
}
state-management.service.ts:
#Injectable
export class StateManagementService
{
private subjectConfigurations = new BehaviourSubject<ApplicationConfigurationResponse>(null);
getApplicationConfigurations(){
return this.subjectSettings.asObservable().pipe(filter(k) => k!=null);
}
set saveApplicationConfiguration(state: ApplicationConfigurationResponse)
{
this.subjectConfigurations.next(state);
}
}
master.component.ts:
#Component({
selector: 'app-master',
..
..
})
export class MasterComponent implements OnInit
{
constructor(private myService: MyService,
private stateService: StateManagementService) {}
ngOnInit():void {
this.myService.getApplicationConfigurationsFromBackend().subscribe((res) ==> {
this.stateService.saveApplicationConfiguration = res;
}
}
header.component.ts:
#Component({
selector: 'app-header',
..
..
})
export class HeaderComponent implements OnInit
{
applicationConfigurationResponse$ : Observable<ApplicationConfigurationResponse>();
constructor(private stateService: StateManagementService) {}
ngOnInit():void {
this.applicationConfigurationResponse$ = this.stateService.getApplicationConfigurations;
}
}
header.component.html:
<div>
<select class="dropdown">
<option *ngFor="let setting of applicationConfigurationResponse$.settings | async" [value] = "setting.settingId">
{{ setting.name }}
</option>
</select>
</div>
But I am getting error on below line:
I am not able to access the property which is wrapped inside an observable.
How can I access the Settings[] from ApplicationConfigurationResponse and populate a dropdown?
You need to access the observable, subscribe to it, then use the settings property using Async Pipe, or you can do something like this
export class HeaderComponent implements OnInit {
applicationConfigurationResponse$ :
Observable<ApplicationConfigurationResponse>();
constructor(private stateService: StateManagementService) {}
ngOnInit():void {
this.applicationConfigurationResponse$ =
this.stateService.getApplicationConfigurations;
}
get settings() {
return this.applicationConfigurationResponse$.pipe(map(res => res.settings));
}
}
and in html
<div>
<select class="dropdown">
<option *ngFor="let setting of settings | async" [value]="setting.settingId">
{{ setting.name }}
</option>
</select>
</div>
I am using a filter and need to read the value in order to send an API request with the values in the url.
I use this API. I am able to filter both of the categories. After selecting two, we wanna send an API request with both selected values in the url.
We generated a backend-side script to filter, all I need to do is sending a request with the modified url.
app.component.ts
import { Component } from "#angular/core";
import { HttpClient } from "#angular/common/http";
#Component({
selector: "my-app",
templateUrl: "./app.component.html",
styleUrls: ["./app.component.css"]
})
export class AppComponent {
lines: any[];
filteredLines: any[];
filterBy;
constructor(private http: HttpClient) {}
ngOnInit() {
this.http.get("https://api.mocki.io/v1/26fce6b9").subscribe(lines => {
this.lines = lines;
this.filteredLines = [...this.lines];
});
}
filter() {
this.filteredLines = [
...this.lines.filter(dropdown => dropdown.name.includes(this.filterBy))
];
}
/** Here I need a script onClick button that reads the selected values and sending a get-request of API link above added with the filtered values:
With click on the submit-button, I want to send the API request.
If api.com/data is the link, the request link would be like api.com/data?line=A&workCenter=1
The "?" is for category Line, and "&" for workCenter.
**/
}
}
app.component.html
<select>
<option>Line</option>
<option *ngFor="let dropdown of filteredLines" (keyup)="filter()">
{{dropdown.line}}
</option>
</select>
<select>
<option>Work Center</option>
<option *ngFor="let dropdown of filteredLines" (keyup)="filter()">
{{dropdown.workCenter}}
</option>
</select>
<form action="" method="post">
<input type="submit" name="request" value="Submit" />
</form>
I have created a Stackblitz project for better understanding.
From your example, you need to add [(ngModel)] which will bind to the selected value.
You can find more info on how to properly use a select here More info
<select [(ngModel)]="selectedLine">
<option>Line</option>
<option *ngFor="let dropdown of filteredLines" (keyup)="filter()">
{{dropdown.line}}
</option>
</select>
<select [(ngModel)]="selectedWorkCenter">
<option>Work Center</option>
<option *ngFor="let dropdown of filteredLines" (keyup)="filter()">
{{dropdown.workCenter}}
</option>
</select>
<form action="" method="post">
<input type="submit" name="request" value="Submit" (click)="Submit()" />
</form>
Then in your ts file, declare the select variable and access value as in the click function Submit.
import { Component } from "#angular/core";
import { HttpClient } from "#angular/common/http";
#Component({
selector: "my-app",
templateUrl: "./app.component.html",
styleUrls: ["./app.component.css"]
})
export class AppComponent {
lines: any[];
filteredLines: any[];
filterBy;
selectedLine; // For first select
selectedWorkCenter; // For second select
constructor(private http: HttpClient) {}
ngOnInit() {
this.http.get("https://api.mocki.io/v1/26fce6b9").subscribe(lines => {
this.lines = lines;
this.filteredLines = [...this.lines];
});
}
filter() {
this.filteredLines = [
...this.lines.filter(dropdown => dropdown.name.includes(this.filterBy))
];
}
requestAnDieAPI() {
console.log(this.filteredLines); // hier muss mein API post request hin
}
Submit() {
var baseUrl = `https://api.mocki.io/`;
var url = `${baseUrl}data?line=${this.selectedLine}&workCenter=${
this.selectedWorkCenter
}`;
this.http.get(url).subscribe(response => {
// response
});
}
}
It is not clear for me if you want to send multiple { line, workCenter } objects to the API call, but from how you setted up the Stackblitz project I will assume you want to send just a single one.
Never seen a (keyup) on an <option> element, use [(ngModel)] on the <select> instead:
<select [(ngModel)]="selected.line">
<option [value]="null">Line</option>
<option *ngFor="let dropdown of filteredLines" [value]="dropdown.line">
{{dropdown.line}}
</option>
</select>
<select [(ngModel)]="selected.workCenter">
<option [value]="null">Work Center</option>
<option *ngFor="let dropdown of filteredLines" [value]="dropdown.workCenter">
{{dropdown.workCenter}}
</option>
</select>
<!-- the use of the form in this case is not required -->
<!-- since you are using requestAnDieAPI to do the api call -->
<form action="" method="post" (submit)="requestAnDieAPI()">
<input type="submit" name="request" value="Submit" />
</form>
<!-- You can also use just a simple button -->
<button (click)="requestAnDieAPI()">Submit</button>
Then your component (model) should contain a selected variable that map the interface (view)
import { Component } from "#angular/core";
import { HttpClient } from "#angular/common/http";
#Component({
selector: "my-app",
templateUrl: "./app.component.html",
styleUrls: ["./app.component.css"]
})
export class AppComponent {
lines: any[];
filteredLines: any[];
filterBy;
selected = {
line: null,
workCenter: null
};
constructor(private http: HttpClient) {}
ngOnInit() {
this.http.get("https://api.mocki.io/v1/26fce6b9").subscribe((lines: any[]) => {
this.lines = lines;
// this.filteredLines = [...this.lines];
// better:
this.filteredLines = this.lines.slice();
// or either this.filter() directly
});
}
filter() {
// this.filteredLines = [
// ...this.lines.filter(dropdown => dropdown.name.includes(this.filterBy))
// ];
// this is redundant, better:
this.filteredLines = this.lines.filter(dropdown => dropdown.name.includes(this.filterBy))
}
requestAnDieAPI() {
if (this.selected.line != null && this.selected.workCenter != null) {
let apiUrl = "https://api.com/data?line=" + this.selected.line +
"&workCenter=" + this.selected.workCenter
this.http.get(apiUrl).subscribe(/* Your optional response callback/subscriber here */);
}
}
}
I was having requirement to translate the dropdown values if user change different language.
I know one solution to use the pipe and transform async behavior but thinking if we have better solution than this.
below is code for solution.
translate-options.pipe.ts
#Pipe({
name: 'translateOptions',
})
export class TranslateOptionsPipe implements PipeTransform, OnDestroy {
constructor(private translateService: TranslateService) { }
transform(items: any) {
const observable = Observable.create(observer => {
this.translateService.get(items).subscribe(result => {
// result will be an object
// e.g. { 'JOBS.UX': 'UX Designer', 'JOBS.DEVELOPER': 'Developer' }
observer.next(result);
});
this.translateService.onLangChange.subscribe(event => {
this.translateService.get(items).subscribe(result => {
observer.next(result);
});
})
});
return observable;
}
ngOnDestroy() {
this.translateService.onLangChange.unsubscribe();
}
}
app.component.html
<ng-select
[addTag]="true"
[addTagText]="to.addTagText || 'Create item: '"
[multiple]="to.multiple"
[closeOnSelect]="!to.multiple"
(change)="onAutoCompleteChange($event)"
>
<ng-option
*ngFor="let item of items | translateOptions | async | keyvalue"
[value]="item.key"
>
{{ item.value }}
</ng-option>
</ng-select>
I'm trying to build a "quick order" component for ordering movies.
The first element is a 'select'. i get the results via http request and then render the options.
When the user is choosing an option of a movie, i need to display him another select which shows available dates. i need to render the select according to an object who got string dates as his keys.
e.g:
{
"2018-07-19": {
"00:10": "5b4f445da2c93e36c4f1a1ca",
"01:00": "5b4f355ab6334b27fc031adb",
"13:44": "5b4f43fda2c93e36c4f1a1c9"
},
"2018-07-25": {
"23:00": "5b4f357db6334b27fc031adc"
}
}
everything is working fine with the rendering of the movieList select and with retrieving the dates object. but when i add the html code of the second select (id=selectDate), i get an error.
Here is my code:
ts:
import { Component, OnInit } from '#angular/core';
import { MoviesService } from '../services/movies.service';
import { ShowService } from '../services/show.service';
import { Observable } from 'rxjs';
import * as moment from 'moment';
#Component({
selector: 'app-quick-order',
templateUrl: './quick-order.component.html',
styleUrls: ['./quick-order.component.css']
})
export class QuickOrderComponent implements OnInit {
movieList: any;
movieShowsSchedule: any;
selectedMovie: any;
selectedDate: any;
constructor(private moviesService: MoviesService, private showService: ShowService) { }
ngOnInit() {
this.movieList = this.moviesService.getMovies();
}
onChangeSelectMovie() {
this.movieShowsSchedule = this.showService.getMovieSchedule(this.selectedMovie).subscribe(res => {
alert("we got movie successfully");
console.log(res);
}, err => {
alert("we did not get movie");
});
}
onChangeSelectDate() {
}
}
html:
<div class="form-group">
<label for="selectMovie">Movie:</label>
<select id="selectMovie" [(ngModel)]="selectedMovie" (change)="onChangeSelectMovie()">
<option *ngFor="let movie of movieList | async" value="{{movie._id}}" >{{movie.title}} </option>
</select>
<label for="selectDate">Date:</label>
<select id="selectDate" [(ngModel)]="selectedDate" (change)="onChangeSelectDate()">
<option *ngFor="let date in movieShowsSchedule | async" value="{{date}}" >{{date}}</option>
</select>
</div>
Anybody knows what is the problem? and how can make this code work?
Many thanks!
There are several issues.
Since you're using async, you should set moveShowSchedule to the result of the Observable not the Subscription, or easier still, don't use async.
You can use map to convert movieShowSchedule into a usable model for your view.
You should replace in with of in the *ngFor.
COMPONENT
movieShowsSchedule = [];
onChangeSelectMovie() {
this.showService.getMovieSchedule(this.selectedMovie).subscribe(x => {
this.moveShowSchedule = [];
for (let key in x) {
this.moveShowSchedule.push({ key, date: x[key].date });
}
});
}
HTML
<option *ngFor="let x of movieShowsSchedule" [ngValue]="x.date">
{{x.date}}
</option>
I didn't want to refactor your whole code, but if you created an Observable bound to the change event you could then use switchMap to update a movieShowSchedule Subject.
I have worked on angular 4 project, In this project, I have a requirement to set the first option as selected where all options are created dynamically by loop.
html code:
<select [(ngModel)]="selectedServiceType" [ngModelOptions]="{standalone: true}" (ngModelChange)="getServiceType($event)">
<ng-container *ngFor="let service of services">
<option [ngValue]="service">{{service.name}}</option>
</ng-container>
</select>
If anyone know about let me know. Thanks in advance!
Try like this :
<select class="form-control" (change)="onChange($event)">
<option *ngFor="let service of services; let itemIndex = index" [selected]="itemIndex == 0" [ngValue]="service.value">{{service.name}}</option>
</select>
component.ts
export class HomeComponent implements OnInit {
private selectedServiceType: any;
private services: Array<any> = [];
constructor() {
this.services = [{
name: "Harish",
value: 5000
}, {
name: "Chandru",
value: 5001
}]
}
onChange(e) {
this.selectedServiceType = e.target.value;
}
}
Just in your ts, inside ngOnInit
selectedServiceType : any;
ngOnInit() {
//make sure you have values for **`services`**
this.selectedServiceType = services[0];
}
add this code
<select (change)="onChange($event.target.value)" value={{selectedService}}>
<ng-container>
<option *ngFor="let service of services" >{{service.name}}</option>
</ng-container>
</select>
and you component.ts should be
export class YourClass implements OnInit {
selectedService: any;
services:any = [];
--your API call code set values to services array
this.services=this.service.APImethod()
onChange(newValue) {
this.selectedService=newValue;
}
}