I have got a weird situcation here. I have a select control on a web page with angular. It shows correctly in local environment.
However, when I published it to Azure, The select control does not show correctly.
This is local showing.
This is on Azure site showing.
This is inspect of select control on local site. Which looks good.
This is inspect of select control on Azure site. As it can be seen that, the select control is empty.
Here is the html for select control, I create a component for customize showing.
<div class="dynamic-field row" [formGroup]="group">
<label class="col-form-label" [ngClass]="'col-'+config.labelSize" *ngIf="config.labelSize!==0">{{ config.label }}</label>
<div [ngClass]="'col-'+ (12 - (config.labelSize||0))">
<div class="input-group input-group-sm">
<div class="input-group-prepend" *ngIf="config.prepend">
<span class="input-group-text" *ngIf="!config.prependConfig" [innerHTML]="config.prepend"></span>
<span class="input-group-text cursor-pointer" *ngIf="config.prependConfig" cspsDynamicFormModalLink [innerHTML]="config.prepend"
[config]="config.prependConfig"></span>
</div>
<select [formControlName]="config.name" class="form-control">
<option [ngValue]="undefined" *ngIf="config.placeholder">{{ config.placeholder }}</option>
<option [ngValue]="option.key" *ngFor="let option of options">
{{ option.value }}
</option>
</select>
<div class="input-group-append" *ngIf="config.append">
<span class="input-group-text" *ngIf="!config.appendConfig" [innerHTML]="config.append"></span>
<span class="input-group-text cursor-pointer" *ngIf="config.appendConfig" cspsDynamicFormModalLink [innerHTML]="config.append"
[config]="config.appendConfig"></span>
</div>
</div>
</div>
</div>
Here is the ts file:
#Component({
selector: 'form-select',
templateUrl: 'form-select.component.html',
styleUrls: ['form-select.component.css']
})
export class FormSelectComponent implements Field, OnInit {
config: FieldConfig;
group: FormGroup;
options: { key: any, value: string }[];
ngOnInit() {
const sorter = {
asc: (a: { value: string }, b: { value: string }) => { return a.value === b.value ? 0 : (a.value > b.value ? 1 : -1) },
desc: (a: { value: string }, b: { value: string }) => { return a.value === b.value ? 0 : (a.value < b.value ? 1 : -1) },
none: undefined
}
this.config.sortOptions = this.config.sortOptions || 'none';
if (this.config.options)
this.options = this.config.options.sort(sorter[this.config.sortOptions]);
else
this.options = [];
}
}
Could anyone give me some suggestions? Or tell me what's going on?
Thanks
Related
I am work in angular. I would like the user to be able to set up lesson subjects and a specific number of hours for a given student group.
group.component.html:
<!--list of groups -->
<div *ngFor="let group of groups">
<div><button (click)="Edit()">Edit group</button></div>
<!--mode without edit -->
<div *ngIf="edit==false">
<tr>Name:{{group.name}}</tr>
</div>
<!--mode with edit -->
<div *ngIf="edit==true">
<tr>Name:<input type="text" value="{{group.name}}" [(ngModel)]="group.name m[ngModelOptions]="{standalone: true}"></tr>
<!--add Subject and set amount hours -->
<!-- add one or more empty subject, select subject and set amount hours-->
<tr>Subjects:</tr>
<button (click)="addSubject()">add</button>
<!-- list of subjects for one group-->
<form>
<div *ngFor="let sub of yourSubjects; let i=index">
<select class="form-control">
{{group.name}}
<option *ngFor="let sub2 of subjectsList" value="{{sub2.name}}">{{sub2.name}}</option>
<input type="hide" [(ngModel)]="groupItem.subjects[[i][0]]" [ngModelOptions]="{standalone: true}">
</select>
<!-- set amount hours for one subject -->
<!--kind of lessons, for one subject -->
Lecture(h)<input type="text" [(ngModel)]="groupItem.subjects[[i][1]]" [ngModelOptions]="{standalone: true}">
workout(h)<input type="text" [(ngModel)]="groupItem.subjects[[i][2]]" [ngModelOptions]="{standalone: true}">
laboratory(h)<input type="text" [(ngModel)]="groupItem.subjects[[i][3]]" [ngModelOptions]="{standalone: true}">
<button (click)="deleteSubject()">Delete</button>
</div>
<!--send data to function -->
<input type="submit" value="Submit" (click)="Edit();updateGroup({id : group.id, name : group.name, yourAllSubjects : groupItem.subjects})">
</form>
</div>
</div>
group.component.ts:
import { Component, OnInit } from '#angular/core';
import {GroupsApiService, RoomsApiService, SubjectsApiService} from "../../../api.services";
import {Groups} from "../../../models/groups.model";
import {Subjects} from "../../../models/subjects.model";
#Component({
selector: 'app-group',
templateUrl: './group.component.html',
styleUrls: ['./group.component.css']
})
export class GroupComponent implements OnInit {
constructor(private groupsApiService:GroupsApiService, private subjectsApiService: SubjectsApiService) { }
groups:Groups[] = [] //list of groups from database
subjectsList:Subjects[]=[] //list of all subjects
groupItem:Groups = new Groups('',1) //one group object
subject:Subjects = new Subjects('',1) // one subject object
number:number = history.state?.data?.title // index one group from groups.component
ngOnInit(): void {
this.groupsApiService.getGroup(this.number).subscribe(data => this.groups = data);
this.subjectsApiService.getSubjects().subscribe(data=>this.subjectsList=data);
// get data from database, data of one group, data of subjects, function from apiservice
}
yourSubjects: Subjects[]=[]; //list of subject for one group
edit=false //say when edit mode on/off
//edit mode
Edit() {
this.edit = !this.edit;
}
// function in html, it send data to database
updateGroup({id, name, yourSubjects}: { id: number, name: string, yourAllSubjects: [][] }){
var arrStr = encodeURIComponent(JSON.stringify(yourSubjects));
this.groupsApiService.editGroup(id,name,arrStr).subscribe()
}
addSubject() {
this.yourSubjects.push(this.subject)
}
deleteSubject(){
this.yourSubjects.pop()
}
}
group.model.ts
export class Groups {
constructor(
public name: string,
public id: number,
public subjects:[][]
) { }
}
apiservice
#Injectable()
export class GroupsApiService {
constructor(private http: HttpClient) {
}
getGroups(): Observable<Groups[]> {
return this.http.get<Groups[]>(`${API_URL}/management/groups`)
}
editGroup(id:number,name: string, yourSubjects?:string){
return this.http.get<Groups[]>(`${API_URL}/management/groups/group/editgroup?id=${id}&name=${name}&subjects=${yourSubjects}`)
}
getGroup(id:number): Observable<Groups[]> {
return this.http.get<Groups[]>(`${API_URL}/management/groups/group?id=${id}`)
}
}
Summary:
The user selects one group and can edit it. He can add specific subjects to it, then specify the number of hours for the types of lessons in a given subject. The number of hours is specified in three text inputs. Then the array saves itself. The array is to keep the names of the items and the individual hours. e.g:
groupItem.subjects[[i][0]]= physics
groupItem.subjects[[i][1]] = 11
groupItem.subjects[[i][2]] = 12
groupItem.subjects[[i][3]] = 30
groupItem.subjects = [{'physics','11','20','30'},{'math','11','20','30'},{'biology','11','20','30'}]
In html have function:
```
<input type="submit" value="Submit" (click)="Edit();updateGroup({id : group.id, name : group.name, yourAllSubjects : groupItem.subjects})">
and in groyp.component.ts:
```
updateGroup({id, name, yourSubjects}:{ id: number, name: string, yourAllSubjects: string[][] })
{ var arrStr = encodeURIComponent(JSON.stringify(yourSubjects)); this.groupsApiService.editGroup(id,name,arrStr).subscribe()
}
Next url is send to backend. Unfortunalety i have null in subject:
http://localhost:5000/management/groups/group/editgroup?id=6&name=example&subjects=[]'
what to do to send arrays correctly in url?
I want to loop through two different arrays with ngFor and display them in html.
<div class="form-check ml-5" *ngFor="let item of competencias.competencias; let i = index">
<input class="form-check-input" type="checkbox" [value]="item.id [(ngModel)]="arrayCompetencias[i].checked">
<label class="form-check-label">
<strong> {{ item.id }} </strong> : {{ item.descripcion}}
</label>
</div>
Those 2 arrays has the same length but I want to combine them as to show separate data.
First array has a list of data just to display and is fine.
Second array arrayCompetencias I want just to see if user check the checkbox or not and save it as ngModel.
When trying to get the parameter data in arrayCompetencias[i].checked it through me an error that the field is undefined, but I am initializing them before.
First Array
competencias = [{id: string, descripcion: string}]
Second Array
arrayCompetencias = [{checked: boolean, id: string}]
[(ngModel)]="arrayCompetencias[i].checked">
How can i read only this field into the array and set according User checked or not
I fixed some typos on your code and added some edits.
Try to use this example and it should work perfectly with you.
import { Component } from '#angular/core';
#Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent {
competencias = [{id: "1", description: "This is a description"}]
arrayCompetencias = [{checked: true, id: "1"}]
}
<div *ngFor="let item of competencias; let i = index">
<input type="checkbox"
[value]="item.id"
[checked]="arrayCompetencias[i].checked"
(change)="arrayCompetencias[i].checked = !arrayCompetencias[i].checked">
<label>
<strong> {{ item.id }} </strong> : {{ item.description}}
</label>
</div>
Nothing I have changes only a problem in your data.
You can check the code here
I'm trying to filter posts of a table in Angular using pipes, but I keep getting on the console this error: core.js:12689 Can't bind to 'ngForFilter' since it isn't a known property of 'a'.
I think the error is on filter: filterPost, but dont know how to fix it. Any clue?
My html code is the following.
<div class="form-group">
<label for="exampleFormControlInput1">Busca un reporte</label>
<input type="text" class="form-control" id="exampleFormControlInput1" name="filterPost" placeholder="Busca.." [(ngModel)]="filterPost">
</div>
<a *ngFor="let report of All_reports | paginate: { itemsPerPage: 10, currentPage: actualPage }; let i = index;
filter: filterPost" class="list-group-item list-group-item-action flex-column align-items-start" [routerLink]="['/reporte-admin']"
routerLinkActive="router-link-active" (click)="onSubmit(report._id)">
<div class="d-flex w-100 justify-content-between">
<h5 class="mb-1">Reporte #: {{report._id}}</h5>
<small>{{i+1}}</small>
</div>
<p class="mb-1">Comentario: {{report.comentario}}</p>
<small class="text-muted">Nombre: {{report.nombre}} {{report.apellido}}</small>
</a>
<br>
This is my filter.pipe.ts code:
#Pipe({
name: 'filter'
})
export class FilterPipe implements PipeTransform {
transform(value: any, arg: any): any {
const resultPosts = [];
for(const report of value){
if(report._id.indexOf(arg) > -1){
resultPosts.push(report);
};
};
return resultPosts;
}
}
Pipe operator "|" expects some value to the left of it.
In your case, you added the pipe operator at the end after let i=index;
I believe you should do something like this
*ngFor="let report of All_reports | paginate: { itemsPerPage: 10, currentPage: actualPage } | filter: filterPost; let i = index;"
and also dont forget to add in declarations in app module
I have this json:
[
{"country" : "Afghanistan","city" : "Kabul"},
{"country" : "Albania","city" : "Tirana"},
{"country" : "Algeria","city" : "Alger"},
And I want to have a select that when choosing a country, I get the city displayed
My service:
getCountries(name?: string, city?: string, expectancy?: string, polulation?: string, government?: string) {
let cities = this.http.get('assets/capitals.json'); -> this is the one called
let language = this.http.get('assets/languages.json');
return forkJoin([cities, language]);
}
Component:
ngOnInit() {
this.weatherService.getCountries()
.subscribe(dataList => {
this.cities = dataList[0]
console.log(this.capitals)
this.population = dataList[1]
console.log(this.cities, this.population)
})
}
onChange(deviceValue) {
console.log(deviceValue)
}
View:
<div class="container">
<div class="row">
<div class="col-md-6 offset-md-3">
<select (change)="onChange($event.target.value)" class="form-control">
<option style="color:black" *ngFor="let c of cities" value="{{c.country}}">{{c.country}}</option>
</select>
</div>
</div>
</div>
It sounds very simple but something is missing. If it were an API I would pick up the select value and make another call with that value on url, but like this, how can I achieve it?
Your function is logging the value of the "select" component which in your case happens to be the country. If you want to display the country but use the city as the value, you simply change the following in the HTML:
<select (change)="onChange($event.target.value)" class="form-control">
<option style="color:black" *ngFor="let c of cities" value="{{c.city}}">{{c.country}}</option>
</select>
Using the above, the country will be displayed but your "onChange" function will log the city value. If you wish to do something else with the city value, you can do so in your onChange function.
So, before You read the whole error stack, keep in mind that at this time I cant pinpoint the exact piece that causes the problem. However, I will disclose the code below the error stack. So, my only question is: what parameters can't be resolved?
If you like, you can test my application for yourself. It is a simple default angular 6 application with all the default settings you get from the following command below:
ng new app-name
let's begin with the error. The application starts like normal. When I try to run the code, this error pops up: Uncaught Error: Can't resolve all parameters for Component: ([object Object]?). You can read the full error stack below.
Uncaught Error: Can't resolve all parameters for Component: ([object Object]?).
at syntaxError (compiler.js:1016)
at CompileMetadataResolver.push../node_modules/#angular/compiler/fesm5/compiler.js.CompileMetadataResolver._getDependenciesMetadata (compiler.js:10917)
at CompileMetadataResolver.push../node_modules/#angular/compiler/fesm5/compiler.js.CompileMetadataResolver._getTypeMetadata (compiler.js:10810)
at CompileMetadataResolver.push../node_modules/#angular/compiler/fesm5/compiler.js.CompileMetadataResolver.getNonNormalizedDirectiveMetadata (compiler.js:10429)
at CompileMetadataResolver.push../node_modules/#angular/compiler/fesm5/compiler.js.CompileMetadataResolver.loadDirectiveMetadata (compiler.js:10291)
at compiler.js:23865
at Array.forEach (<anonymous>)
at compiler.js:23864
at Array.forEach (<anonymous>)
at JitCompiler.push../node_modules/#angular/compiler/fesm5/compiler.js.JitCompiler._loadModules (compiler.js:23861)
syntaxError # compiler.js:1016
push../node_modules/#angular/compiler/fesm5/compiler.js.CompileMetadataResolver._getDependenciesMetadata # compiler.js:10917
push../node_modules/#angular/compiler/fesm5/compiler.js.CompileMetadataResolver._getTypeMetadata # compiler.js:10810
push../node_modules/#angular/compiler/fesm5/compiler.js.CompileMetadataResolver.getNonNormalizedDirectiveMetadata # compiler.js:10429
push../node_modules/#angular/compiler/fesm5/compiler.js.CompileMetadataResolver.loadDirectiveMetadata # compiler.js:10291
(anonymous) # compiler.js:23865
(anonymous) # compiler.js:23864
push../node_modules/#angular/compiler/fesm5/compiler.js.JitCompiler._loadModules # compiler.js:23861
push../node_modules/#angular/compiler/fesm5/compiler.js.JitCompiler._compileModuleAndComponents # compiler.js:23839
push../node_modules/#angular/compiler/fesm5/compiler.js.JitCompiler.compileModuleAsync # compiler.js:23799
push../node_modules/#angular/platform-browser-dynamic/fesm5/platform-browser-dynamic.js.CompilerImpl.compileModuleAsync # platform-browser-dynamic.js:143
push../node_modules/#angular/core/fesm5/core.js.PlatformRef.bootstrapModule # core.js:4352
./src/main.ts # main.ts:11
__webpack_require__ # bootstrap:76
0 # main.ts:12
__webpack_require__ # bootstrap:76
checkDeferredModules # bootstrap:43
webpackJsonpCallback # bootstrap:30
(anonymous) # main.js:1
As you see, there is no easy way of telling which part of my typescript is causing the problem. However, The application runs fine without the code in component.ts shown below. So, there is definitely something wrong with my typescript component.ts
the component.ts is shown below:
import {Component, ElementRef, EventEmitter, Input, OnInit, Output, ViewChild, Directive} from '#angular/core';
import { FormGroup } from '#angular/forms';
import { DefineBusinessRuleService } from '../services/define/define-business-rule.service';
import { DefineBusinessRuleNamespace } from '../model/business-rule-namespace';
#Component({
selector: 'app-define-business-rule',
templateUrl: './define-business-rule.component.html',
styleUrls: ['./define-business-rule.component.css']
})
export class DefineBusinessRuleComponent implements OnInit {
// interfaces
headers : Headers;
output: any;
#Input() minValue: string;
#Input() maxValue: string;
#Input() attribute : Array<string>;
#Input() table : Array<string>;
submitted = false;
#Input() businessRuleType : Array<string>;
ruletypes : Array<string>;
ruletype : string;
constructor(
private defineBusinessRuleService: DefineBusinessRuleService
,private model : any
) {
this.table = ['table1', 'table2', 'table3'];
this.attribute = ['attribute1', 'attribute2', 'attribute3'];
this.ruletypes = [
// atrribute
'AttributeRange',
'AttributeCompare',
'AttributeList',
'AttributeOther',
'TupleCompare',
'TupleOther'
]
model = {
minValue : 5,
maxValue : 10,
name : 'RangeRule',
description : 'This is a Range Rule',
table1 : this.table[0],
column1 : this.attribute[2],
errorMsg : 'Error message'
};
}
get diagnostic() { return JSON.stringify(this.model); }
defineNewBusinessRule() {
//this.model = new DefineBusinessRuleService(42, 50, '', '', '', '', '');
}
saveAttributeRangeRule(){
this.output = {
database_id : 1,
minValue : this.minValue,
maxValue : this.maxValue,
table1 : this.table,
column1 : this.attribute
}
this.output.stringify;
this.defineBusinessRuleService.saveAttributeRangeRule(this.output);
}
saveAttributeCompareRule(){
this.output = {
database_id : 1,
table1 : this.table,
//table2 : this.table2,
column1 : this.attribute,
//column2 : this.attribute2,
//value : this.value
}
this.output.stringify;
//this.defineBusinessRuleService.saveAttributeCompareRule(this.output);
}
ngOnInit(){
}
onSelect(){
}
onSubmit() {
this.submitted = true;
this.ruletype = this.ruletypes[0];
switch(this.ruletype){
case "AttributeRange" : {
this.saveAttributeRangeRule();
break;
};
case "AttributeCompare" : {
this.saveAttributeCompareRule();
break;
};
}
}
}
Thanks for reading this! If you are visually orientated like me, then this form might help you understand what this code should do. However, it's off topic, since i'm certain enough that it doesn't cause operational problems in angular. keep that in mind!
the related html form is shown below
<br>
<br>
<main role="main" class="container">
<div class="container">
<h1>Define Business Rule</h1>
<form (ngSubmit)="onSubmit()" #defineBusinessRuleForm="ngForm">
<div class="form-group">
<label for="minValue">Minimum Value</label>
<input type="text" class="form-control" id="minValue">
</div>
<div class="form-group">
<label for="maxValue">Maximum Value</label>
<input type="text" class="form-control" id="maxValue">
</div>
<div class="form-group">
<label for="name">Name</label>
<input type="text" class="form-control" id="name" required [(ngModel)]="model.name" name="name"
#name="ngModel">
<div [hidden]="name.valid || name.pristine"
class="alert alert-danger">
Name is required
</div>
</div>
<div class="form-group">
<label for="description">Description</label>
<input type="text" class="form-control" id="description" required>
</div>
<div class="form-group">
<label for="table">Table</label>
<select class="form-control" id="table" required>
<option *ngFor="let tbl of table" [value]="table">{{tbl}}</option>
</select>
</div>
<div class="form-group">
<label for="attribute">Attribute</label>
<select class="form-control" id="attribute" required>
<option *ngFor="let attr of attribute" [value]="attribute">{{attr}}</option>
</select>
</div>
<div class="form-group">
<label for="errorMsg">Error Message</label>
<input type="text" class="form-control" id="errorMsg" required>
</div>
<button type="submit" class="btn btn-success" [disabled]="!defineBusinessRuleForm.form.valid">Submit</button>
<button type="button" class="btn btn-default" (click)="defineNewBusinessRule(); defineBusinessRuleForm.reset()">Define New BR</button>
</form>
</div>
</main>
The error is in the model definition location.
private model: any should be defined as a parameter outside of a constructor.
By placing it in the constructor, the compiler is trying to resolve any class, and, naturally is unable to do so.
Modify your code this way:
export class DefineBusinessRuleComponent implements OnInit {
private model : any
constructor() {
this.model = {
// your model definition
};
}
// rest of the code
}