why formgroup is not detecting changes on select element in Angular - javascript

For some reason, change is not detected on the select element in Angular reactive form. Below is the code extract
Component html code
<form (ngSubmit)="onSubmit()" [formGroup]="postProjectForm">
<div class="form-group">
<label>Job Type:</label>
<select formControlName="jobType" (change)="onChange($event.target.value)" >
<option *ngFor="let jt of jobTypes" [value]="jt">{{jt}}</option>
</select>
</div>
</form>
Component js code
jobTypes = ['Full time', 'Part time', 'Intership', 'Freelancing'];
constructor(private fb: FormBuilder){
this.postProjectForm = this.fb.group({jobType: new FormControl(this.jobTypes[0])})
}
onSubmit() {
console.log(this.postProjectForm.get('jobType').value);
}
onChange(val){
console.log(val);
}
The code starts fine, i.e. the select is populated with three four values with 'Full Time' as default value. However, when I change the option and submit, the onSubmit method logs the initial value ( Full Time ).
Also the onChange method does not fire at all!

Try updating: <select formControlName="jobType" (change)="onChange($event.target.value)" >
to <select formControlName="jobType" (change)="onChange($event.target)" >
and onChange(val){ console.log(val); } to onChange(val){ console.log(val.value); } and see if the onChange event now works. If this works, then the form should also work. I don't see any other reason why it won't.
If so, I can probably explain what's happening.

Related

Select selected option not working for some reason =/

[For some reason the selected select option not showing any value just a blank area only when clicking it it shows the values. ive checked the css files and it seems fine no idea what causes the problem when i remove the [(ngModel)] it works but not getting the values =/
import { Component, OnInit } from '#angular/core';
import { Company } from '../_models/company';
import { CompanyService } from '../_services/company.service';
import { AlertifyService } from '../_services/alertify.service';
#Component({
selector: 'app-company',
templateUrl: './companies.component.html',
styleUrls: ['./companies.component.css']
})
export class CompaniesComponent implements OnInit {
selectedCompany: Company;
companies: Company[];
constructor(private companyService: CompanyService, private alertify: AlertifyService) { }
ngOnInit() {
this.loadCompanies();
}
async loadCompanies() {
this.companyService.getCompanies().subscribe((companies: Company[]) => {
this.companies = companies;
}, error => {
this.alertify.error(error);
});
}
// selectedChangeHandler(event: any) {
// this.selectedCompany = event.target.value;
// }
}
<ng-container *ngIf="companies">
<div class="col-12 col-md-3 col-xl-2 mt-5 bd-sidebar">
<label for="">Select Company</label>
<select class="form-control" [(ngModel)]="selectedCompany" >
<option selected> -- select an option -- </option>
<option *ngFor="let value of companies" [ngValue]="value">{{value.name}}</option>
</select>
</div>
</ng-container>
<!--Just a test--->
<!-- <select class="form-control col-lg-8" #selectedValue name="selectedValue" id="selectedValue" [(ngModel)]="company" (ngModelChange)="assignCorporationToManage($event)">
<option *ngFor="let value of companies" [ngValue]="company">{{value.name}}</option>
</select> -->
<ul *ngIf="selectedCompany" class="list-group list-group-flush">
<li class="list-group-item">Company name: {{selectedCompany.name}}</li>
<li class="list-group-item">Company address: {{selectedCompany.address}}</li>
<li class="list-group-item">Company estimated revenue: {{selectedCompany.estimatedRevenue}}₪</li>
</ul>
I see several issues with your example, so I am going to offer another approach, and explain what I am doing along the way.
In an Angular application, when using two way binding with [(ngModel)] on a select, the initially selected option will always be set to the one that matches the value of ngModel.
In your example, the initial value for selectedCompany is never set, and that is the reason your initial page load displays the menu with nothing selected. You are going to need to set a value onto all of your options, including the first to get this to work.
Now, since you did not provide the structure of your model titled Company, I am going to improvise and assume it contains two elements, name and value. So just remember, you will need to adjust what I have below to match the actual structure of your data.
First, on the option tags in your select in the template, id suggest using the value attribute which we will be populating with strings, instead of ngValue which is can be used to contain an object or a string. You can obtain the object that contains all of the data you need via the change event later.
Let's adjust your template file as follows:
<select class="form-control" [(ngModel)]="selectedCompany" (change)="companyChange($event.target.value)">
<option [value]="'init'">-- select a company --</option>
<option *ngFor="let company of companies" [value]="company.value">{{company.name}}</option>
</select>
Next, in your component file, lets change that property that we're using for two way binding on your select to be typed as a string:
selectedCompany:string;
Next, lets create a new property typed to your model which we will ultimately set to the company selected:
myCompany:Company;
Next, set the initially selected option in your component so that '-- select a company --' will display as the initially selected option:
ngOnInit() {
this.selectedCompany = 'init';
this.loadCompanies();
}
And lastly, inside the change event, you can use the find() method to obtain the complete set of data that you need:
companyChange(value) {
this.myCompany = this.companies.find(element => element.value === value);
console.log("User selected the company:", this.myCompany);
}

VueJS v-model not working on select tag when bound with dynamic property

I am building an application which will generate a dynamic form for customer feedback reception. Now while adding fields to the form, individual fields have validation rules inlcuding length and type rules, there is also going to be a property on each validation rule, which will determine if that particular rule should be parsed while validating the fields.
I have a Vue data property called fields, which has an object for each field. It looks like this:
export default {
data() {
return {
fields: [{
label: 'Email',
validation: {
length: {
add: 0, // 0 for false, 1 for true
min: 0, // minimum length
max: 0 // maximum length
}
}
}]
}
}
}
Now for enabling the user to select whether validation rule should be enabled or disabled (i.e length.add = 1 or 0) , I have a a select element with two options for their respective values (0 and 1). Here is the template code:
<div v-for="(field, index) in fields">
<div v-for="(rule, key) in field.validation">
<select class="form-control" v-model="fields[index].validation[key].add">
<option :value="1">Enabled</option>
<option :value="0">Disabled</option>
</select>
</div>
</div>
Everything is working fine such as the v-model on select is mutating the value in the data property, but the select isn't showing the default value which is selected, here is what it looks like after rendering:
Can someone please tell me why isn't it working? I also tried replacing v-model with the value attribute, but no luck!
Hi I think you should try the :key attribute in the options field. Set there the value for the key. The first option should have the value 0 and the second option should have the value 1. Now there should be a mapping between the values.
<div v-for="(field, index) in fields">
<div v-for="(rule, key) in field.validation">
<select class="form-control" v-model="fields[index].validation[key].add">
<option :key="1" :value="1">Enabled</option>
<option :value="0" :value="0">Disabled</option>
</select>
</div>
</div>
Found the problem, it was the WIDTH!
The width of the select tag was to short, hence it wasn't showing the actual text XD XD

Angular2 - update select template from component

I have a select element in my component template that is hooked up a selectedEmp model.I want to be able to update the selectedEmp in the component and have the correct value show in the select element. My current setup is not letting this happen. Instead the select value does not display the selectedEmp. I console logged the selectedEmp, and its value is changing. I think this is because the option element is never set to any value when i do it via the component. Does anyone know a way to do this.
Component.html
<select name="sel1" class="form-control" (ngModelChange)="onChange($event.target.value)" [(ngModel)]="selectedEmp">
<option [value]="employee" *ngFor="let employee of employees">
{{employee}}
</option>
</select>
Component.ts
employees:Array<string> = ["Andrew","Allen","Kevin","Phil"];
visable:boolean = false;
selectedEmp:any = null;
constructor(){}
// Selection change
onChange(value:any):void {
console.log(value);
}
updateModel(){
this.selectedEmp = "Allen"
}
It's not quite clear from your question but I did see one error on your (ngModelChange) event binding, since the items are strings, $event.target.value fails try (ngModelChange)="onChange($event)".
But that was only for console anyway, so removing it leaves:
<button type="button" (click)="updateModel()">Select Allen</button>
<select name="sel1" [(ngModel)]="selectedEmp">
<option [value]="employee" *ngFor="let employee of employees">
{{employee}}
</option>
</select>

Binding an event handler to an HTML select.option

I want to show a warning message if a user selects a specific option, but the warning isn't appearing. How can I modify my code so that this works correctly? Here is a demo on jsFiddle which reproduces the problem?
HTML :
<input type="text" id="mail_address"/>
<select>
<option value='google.com'>google.com</option>
<option onClick="warningaa()" value=''>Don't send mail</option>
</select>
JS:
function warningaa() {
alert('If you choose this option, you can not receive any information');
}
You can not use on click action in dropdown option. One solution is to use change on select element:
html
<input type="text" id="mail_address" />
<select onchange="warningaa(this);">
<option value='google.com'>google.com</option>
<option value='error'>error</option>
</select>
js
function warningaa(obj) {
if(obj.value == "error") {
alert('If you choose this option, you can not receive any infomation');
}
}
fiddle
The option tag does not support the onclick event. Use the onchange event on the select instead.
HTML
<input type="text" id="mail_address"/>
<select id="selectbox" onchange="warning(this)">
<option value='google.com'>google.com</option>
<option value='warning'>Do not send me any kind of shit</option>
</select>
JS
function warning(obj) {
if(obj.value == 'warning') {
alert('If you choose this option, you can not receive any infomation');
}
}
You need to set an event handler on the SELECT element, and watch the "value" of select, as below:
document.getElementById('mySelect').addEventListener('change', warn, true);
function warn(e) {
e.preventDefault();
e.stopPropagation();
if (e.currentTarget.value === 'the value you want') {
// do something
} else {
return;
}
The key here is using CHANGE event vs CLICK, since you want to react to a "change in value" and if that value = something, warn the user.
using addEventListener is also a better approach overall, it clearly distinguishes your HTML from your JavaScript.
More on this here:
https://developer.mozilla.org/en-US/docs/Web/API/EventTarget.addEventListener
and here:
https://developer.mozilla.org/en/docs/Web/API/Event

backbone-forms with conditional fields

First of all thanks to the guys of backbone-forms who made a tool which perfectly integrates in the backbone.js framework.
I'm using backbone.js with the backbone-forms plugin, but I need to make conditional fields.
Let's say I've the following form.
I want to show (or not) a single line input with thext or a textarea according to the value selected in the select.
<form method="post" action="">
<select >
<option value="" selected="selected">choose one</option>
<option value="1" >line</option>
<option value="2" >area</option>
</select>
<input id="element_1" />
<textarea id="element_2" ></textarea>
</form>
A behaviour like this one is implemented by default in backbone?
If not, how can I implement it with javascript and backone-forms?
thanks.
You can bind events to the select element and have them toggle the visibility of other form elements.
Try this:
$(function() {
//The form
var form = new Backbone.Form({
schema: {
inputType: { type: 'Select', options: ['line', 'area'] },
line: 'Text',
area: 'TextArea'
}
}).render();
form.fields['area'].$el.hide();
form.on('inputType:change', function(form, editor) {
form.fields['line'].$el.toggle();
form.fields['area'].$el.toggle();
});
//Add it to the page
$('body').append(form.el);
});
Here's some live code: http://jsfiddle.net/shioyama/grn6y/
Derived from this: https://groups.google.com/d/topic/backbone-forms/X5eVdTZWluQ/discussion
There is no default implementation.In fact, completely on your own is also very simple, please reference the following code:
//Pseudo code
var line = $("element_1"),area = $("element_2");
if(selectvalue ==="1"){
line.show();
area.hide();
}
else{
line.hide();
area.show();
}

Categories

Resources