Angular2 reactive forms dropdown - javascript

I am just learning angular 2 and have a case where I am creating a form that will be a piece of equipment. One of the fields that are associated with the equipment is a building. When the user is editing or adding a new piece of equipment I want them to be presented with a drop-down with a list of the building they can assign the equipment to. The equipment-detail component is as follows:
export class EquipmentDetailComponent implements OnInit {
equipment: IEquipment;
equipmentForm: FormGroup;
buildingList: Ibuilding[];
constructor(private EquipmentService: EquipmentService,
private BuildingsService: BuildingsService) { }
ngOnInit() {
this.equipment = this.EquipmentService.getEquipmentDetail(1);
this.buildingList = this.BuildingsService.getBuildingList();
let id = new FormControl(this.equipment.id);
let unit = new FormControl(this.equipment.unit);
let active = new FormControl(this.equipment.active);
let building = new FormControl(this.equipment.building.id);
this.equipmentForm = new FormGroup({
id: id,
unit: unit,
active: active,
building: building
})
}
saveEquipment(formValues){
console.log(formValues);
}
onSelect(id){
this.equipment.building = this.BuildingsService.getBuildingDetail(id);
console.log(this.equipment.building)
}
}
The equipment-detail html is as follows:
<div class="col-md-2">
<form [formGroup]="equipmentForm" (ngSubmit)="saveEquipment(equipmentForm.value)" autocomplete="off" novalidate>
<div class="form-group">
<label form="unit">Unit:</label>
<input formControlName="unit" id="unit" type="text" class="form-control" placeholder="Unit...."/>
</div>
<div class="form-group">
<label form="active">Active:</label>
<input formControlName="active" id="active" type="checkbox" class="form-control"/>
</div>
<div class="form-group">
<label form="building">Building:</label>
<select class="form-control" formControlName="building" (change)="onSelect($event.target.value)">
<option *ngFor="let building of buildingList" value={{building.id}}>
{{building.buildingName}}
</option>
</select>
</div>
<button type="submit" class="btn btn-primary">Save</button>
</form>
</div>
When I click the dropdown option I get an object that represents the building that I selected. The result is
Object {id: 2, buildingName: "Building 2", active: true}
active: true
buildingName: "Building 2"
id: 2
When I click the save button and look at the data that is associated with the formcontrol the building is no longer an object it is just the buildingId.
Object {id: 1, unit: "Item 1", active: true, building: "2"}
active: true
building: "2"
id: 1
unit:"Item 1"
__proto__: Object
How do I get the main equipment object to be set with the building object and not just the building id?

It is because you had value attribute with building.id, that's why it is assigning building.id on option selection. You should consider changing your value attribute binding to ngValue with whole building object.
<select class="form-control" formControlName="building" (change)="onSelect($event.target.value)">
<option *ngFor="let building of buildingList" [ngValue]="building">
{{building.buildingName}}
</option>
</select>

Related

Angular select pass in JSON option value

Here is a link to my project: https://stackblitz.com/edit/angular-ivy-scycva?file=src/app/form/form.component.ts
I initially have a dropdown, where the user selects one of three users: Jack, Nav, or Pom
After selecting user x, the details of x are displayed below.
I have three datas at the start, and initialize a current object:
datas: Data[] = [
new Data(1, "Jack", "jack#gmail.com", "123 Main"),
new Data(1, "Nav", "nav#gmail.com", "324 Murray"),
new Data(1, "Pom", "pom#gmail.com", "995 Fortran")
];
current: Data = this.datas[0];
The select dropdown selects current.name as the default value. The options are a list of objects inside datas, and we show the data.name property:
<select
id="person"
class="form-control"
[ngModel]="current.name"
#selectRef
(change)="updateSelect(selectRef.value)">
<option *ngFor="let data of datas" id="{{data.name}}" [value]="data.name">{{ data.name }}</option>
</select>
Below are a set of inputs in a form, which should contain data on the person selected:
<form #userForm="ngForm">
<div class="form-group">
<label>Name</label>
<input type="text" class="form-control" name="name" [ngModel]="current.name">
</div>
<div class="form-group">
<label>Email</label>
<input type="text" class="form-control" name="email" [ngModel]="current.email">
</div>
</form>
Currently when an update occurs, I change the current object as follows:
updateSelect(event) {
this.current = this.datas.filter(d => d.name == event)[0];
}
I don't like this way because first of all, names can be the same, and secondly, I feel there must be a better way.
If possible, I want to be able to pass in the data object from the option selected so I can just do this.current = data, but I don't know if this is possible. I also don't want to expose anything like an id onto the option field, which the user should not be able to see.
Modified here https://stackblitz.com/edit/angular-ivy-v1pjhn?file=src%2Fapp%2Fform%2Fform.component.html
Previous
<select
id="person"
class="form-control"
[ngModel]="current.name"
#selectRef
(change)="updateSelect(selectRef.value)"
>
<option *ngFor="let data of datas" id="{{data.name}}" [value]="data.name">{{ data.name }}</option>
</select>
Now
<select
id="person"
class="form-control"
[(ngModel)]="current"
>
<option *ngFor="let data of datas" [ngValue]="data">{{ data.name }}</option>
</select>

Model binding in angular template driven forms doesn't work

I'm trying to bind the model in angular template driven forms. I created a model class and using it to populate the input field.
HTML:
<div class="form-group col-md-2 col-12" [class.text- danger]="nameCode.invalid && nameCode.touched">
<label for="inputName" class="form-control-label"> Name</label>
<input type="text" class="form-control" [class.is-form-invalid]="nameCode.invalid && nameCode.touched" id="inputName" name="lotCode"[(ngModel)]="formModel.name" #nameCode="ngModel" aria-describedby="nameHelp" autocomplete="new-password" required>
<small id="nameHelp" class="text-danger" *ngIf="nameCode.invalid && nameCode.touched">Required</small>
Component:
export class AppComponent {
formModel: FormModel= new FormModel();
}
export class FormModel {
name: "abc"
}
https://stackblitz.com/edit/angular-yue9fe?file=src%2Fapp%2Fapp.component.ts
name: "abc" should be name= "abc" (or name: string = "abc"). Right now you're declaring type of name as "abc", which is not what you want.
You have bind the name as "abc" dataType. So if you want to bind your model with html you can define your formModel class like,
export class FormModel {
constructor(public name="abc"){}
}

Checkbox array in Vue Js

I have an array of checkboxes, coming from a main system object where I store all system setting. (called getSystem{}).
In this form, Im accessing a User, which has an array of roles [].
How can I check this array of roles, against the getSystem.user_roles?
I know how to do it normally, in javascript obviously. But what would I put in the checkbox input Vue.js wise?
<b-form-group>
<label for="company">Email Address</label>
<b-form-input type="text" id="email" v-model="user.email" placeholder="Enter a valid e-mail"></b-form-input>
</b-form-group>
// Here i can do user.roles to get the array of roles.
// What can I do to loop through the roles and check the box if it exists in the user roles??
<b-form-group v-for="resource, key in getSystem.user_roles" v-if="getSystem.user_roles">
<label>{{resource.role_name}}</label>
<input type="checkbox" [ what do I put here to compare against user.roles, and check the box if exists??] >
</b-form-group>
This behavior is well documented on the Checkbox binding Docs.
Here a little example emulating your logic
new Vue({
el: '#app',
data: {
user: {
email: 'test#test.com',
roles: [{id: 1, name: 'Client'}]
},
roles: [
{
id: 1,
name: 'Client',
},
{
id: 2,
name: 'Admin',
},
{
id: 3,
name: 'Guest',
}
]
}
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.16/vue.min.js"></script>
<div id="app">
<div>
<label>Email</label>
<input type="text" v-model="user.email" />
</div>
<div v-for="role in roles" :key="role.id">
<label>{{role.name}}</label>
<input type="checkbox" v-model="user.roles" :value="role"/>
</div>
<p>User's selected roels</p>
{{user.roles}}
</div>
<input type="checkbox" v-model="userRoles" :true-value="[]" :value="resource.role_name">
You should add :true-value="[]".
<b-form-group v-for="resource, key in getSystem.user_roles" v-if="getSystem.user_roles" :key="key">
<label>{{resource.role_name}}</label>
<input type="checkbox" v-model="userRoles" :value="resource.role_name" >
</b-form-group>
<script>
data(){
return {
userRoles: []
}
}
</script>
We can use dynamic check box input rendering with the condition to select values from the customized function (in my example selectUsers). In that function, we can write conditions that we need to compare before append to the selected array.
Demo:
This is the full NuxtJs(vue) component with dummy data.
<template>
<v-container fluid>
<p>{{selected }}</p>
<div v-for="user in user_roles" :key="user[0]">
<input type="checkbox"
#click="()=>{selectUsers(user[0])}"
:value="user[0]"
>
{{user[1]}}
</div>
</v-container>
</template>
<script>
import VueLodash from 'vue-lodash'
import lodash from 'lodash'
export default {
data() {
return {
user_roles:[[1,"dd"],[2,"ddd"],[3,"kksse"],[4,"kske"]] ,
selected:[],
};
},
methods: {
selectUsers(id){
//in here you can check what ever condition before append to array.
if(this.selected.includes(id)){
this.selected=_.without(this.selected,id)
}else{
this.selected.push(id)
}
}
}
}
</script>
In my case, as I am server rendering the checkboxes, what worked for me is to replace :value with just value
#foreach($carOptions as $option)
<div class="form-check">
<input class="mx-2 form-check-input cursor-pointer"
type="checkbox"
value="{{$option}}" <------ HERE in order for vue to work I had to change from :value to value
v-model="offer.carOptions">
<label class="custom-control-label cursor-pointer"
for="leading">{{ __($option) }}</label>
</div>
#endforeach
NOTE: The code snippet is a Laravel Blade Templates.

How to set value to FormBuilder object in angular 2 Typescript

I am used Reactive form Validation(Model driven validation) but cant set the value to form object on Dropdown change
This is my Formgroup
studentModel:StudenModel
AMform: FormGroup;
Name = new FormControl("", Validators.required);
Address = new FormControl("", Validators.maxLength(16));
constructor(fb: FormBuilder){
this.AMform = fb.group({
"Name": this.Code,
"Address": this.Abbrev,
});
}
onAccntChange(event: Event) {
// set the value from Class Model
//// this.studentModel
// how to set this.studentModel value to form
}
This is My html page
<form [formGroup]="AMform" (ngSubmit)="submit()">
<select (change)="onAccntChange($event)" class="form-control" [disabled]="ddlActivity" formControlName="AccountManagerID">
<option value="0">Select</option>
<option *ngFor="let item of allStudent" value={{item.StudentID}}>
{{item.Name}}
</option>
</select>
<div class="col-sm-9">
<input type="text" class="form-control" formControlName="Name">
</div>
<div [hidden]="Name.valid || Code.pristine" class="error"> Name is required </div>
<div class="col-sm-9">
<input type="text" class="form-control" formControlName="Address">
</div>
<div [hidden]="Address.valid || Address.pristine" class="error">Address is required </div>
<button type="submit" class="btn btn-warning "><i class="fa fa-check-square"></i> Save</button>
</form>
On change i need to set the formcontrol value
You can achievie that by invoking setValue method on your FormControl object:
(<FormControl> this.AMform.controls['Name']).setValue("new value");
or:
this.Name.setValue("new value");
Use patchValue method of your FormGroup object.
onAccntChange(event: Event) {
this.AMform.patchValue({yourControl: studentModelValue})
}
Using setValue you need to specify all the FormControls:
this.AMform.setValue({'Name':'val1', 'Address':'val2'})
Using patchValue you can specify just the one you need:
this.AMform.patchValue({'Name':'val1'})
Here you can read a little bit more.

Single field search multi fields auto fill using twitter typeahead.js v0.10.2

I have a data set as like as var links = [{ title : 'title1', link : 'link1', target : 'target1' }, { title : 'title2', link: 'link2', target: 'target2'}
My HTML code as below :
<input type="text" name="title" class="title">
<input type="text" name="link" class="link">
<input type="text" name="target" class="target">
I can set autocomplete for each input field individually using typehead.js (v0.10.2) using my links variables. But is it possible if I set autocomplete for class .title and when typehead:selected event fired, then .link and .target input fields also complete with corresponding values.

Categories

Resources