I'm using AngularJs to change visibility of certain DOM elements. The visibility depends on what value was selected in a dropdownlist. More specifically, on a data-attribute of the selected option tag. I cannot populate the dropdown via AngularJs, because it's an existing ASP.NET control.
I thought about using ng-change and call a method on my controller but I'd have to pass an argument. This argument is in the DOM and not in my controller. Obviously, I'd like to keep it this way, and not access the DOM in my controller.
I've made a jsFiddle, but this is my code:
HTML
<body ng-app>
<div ng-controller="VehicleDetailsCtrl">
<select ng-model="selectedValue" ng-change="update()">
<option value="1" data-carType="Car">Car 1</option>
<option value="2" data-carType="Car">Car 2</option>
<option value="3" data-carType="Truck">Truck</option>
</select>
<div ng-hide="isTruck">
Hide if a truck was selected.
</div>
</div>
</body>
Javascript
function VehicleDetailsCtrl($scope) {
$scope.isTruck = false;
$scope.selectedValue = null;
$scope.update = function() {
$scope.isTruck = !$scope.isTruck;
// hide div here?
// but then I'd need to know the selected option,
// but I don't want to reference the DOM here.
};
}
Am I approaching this in the wrong way?
Keep in mind that I cannot let AngularJs populate the select because ASP.NET already does that for me (and I can't change that at the moment).
Also, I need both the selectedValue (for post-back and saving it to the database) and the data-carType (for changing the DOM). I don't know at runtime what the id (or value) of the Truck option is.
Use a directive to create an object of vehicle types and watch the model value of the select to update your isTruck variable:
HTML:
<select ng-model="selectedValue" check-is-truck>
JS:
var app = angular.module('myApp', []);
app.directive('checkIsTruck', function(){
return function(scope, element, attrs){
scope.vehicleTypes = {};
scope.selectedType = false;
angular.forEach(element.find('option'), function(item, idx) {
scope.vehicleTypes[item.value] = item.dataset.cartype;
});
scope.$watch('selectedValue', function() {
scope.selectedType=scope.vehicleTypes[scope.selectedValue];
scope.isTruck = scope.selectedType == 'Truck'
})
};
})
function VehicleDetailsCtrl($scope) {
$scope.isTruck = false;
$scope.selectedValue = null;
}
DEMO: http://jsfiddle.net/7ttr6/2/
You don't need ng-change to update the value because ng-model takes care of that. And in ng-hide you need to simply compare the selectedValue with the value of 'Truck' option (int 3):
<select ng-model="selectedValue">
<option value="1" data-carType="Car">Car 1</option>
<option value="2" data-carType="Car">Car 2</option>
<option value="3" data-carType="Truck">Truck</option>
</select>
<div ng-hide="selectedValue==3">
Hide if a truck was selected.
</div>
Fiddle
Related
I am looking for some help with my verification code. I am looking for a simple method to verify two ages. There is a "from age" and a "to age". I need to make sure that the user selects the ages properly. The "from age" should be younger than the "to_age. I made a script and it kind of works. The problem is it does not work consistently. I need it to check, when you select the "from_age" dropdown as well as the "to_age" dropdown. This one seems to only work with one of the dropdowns and one time through. It does not work when the page loads and it sometimes doesn't work at all. I tried two options but neither worked. I tried to use localstorage values since another script I have loads the keys and values on change very well. Or I need to try to fix this version which uses the values in the options dropdown. I am not sure which would work better, but I am thinking the localstorage values are the better choice.
I have tried to use the values associated with the keys in localstorage but I failed on getting it to work. The method using the values in the select/options works but works poorly. Please excuse me if I made any mistakes condensing the code for this question. Thanks
jQuery
$(function() {
$('.agefrom_selection').change(function () {
var quantity_1 = parseInt($('.agefrom_selection').val());
var quantity_2 = parseInt($('.ageto_selection').val());
if ( quantity_1 > quantity_2 ) {
$('.age_warning').addClass('show_age_warning')
}
else {
$('.age_warning').removeClass('show_age_warning')
}
});
});
CSS
.age_warning {
display: none;
}
.age_warning.show_age_warning {
display: block;
position: relative;
float: right;
font-size: 12px;
color: #ff0000;
}
html
<form id="ageselection" method="post" autocomplete="off">
<fieldset>
<ul class="age_preference_text_box fl">
<li><label class="from_to_age_text">from </label>
<select class="age_text agefrom_selection">
<option value="18" selected>18</option>
<option value="19">19</option>
<option value="20">20</option>
<option value="21">21</option>
<option value="22">22</option>
</select>
</li>
<li><label class="from_to_age_text">from </label>
<p class="age_warning"> "to" age must be equal <br>or higher than "from" age</p>
<select class="age_text ageto_selection">
<option value="18" selected>18</option>
<option value="19">19</option>
<option value="20">20</option>
<option value="21">21</option>
<option value="22">22</option>
</select>
</li>
</ul>
</fieldset>
</form>
I expected the warning to show on every instance(or disappear). If you change the from_age dropdown, when you change the to_age dropdown, when you modify either dropdown, if you refresh the page, and if you manipulate any dropdown after a page refresh. My code is poorly written and does not work as expected.
I figured it out. The function was only written on one of the dropdown selectors. It needed to be written for both dropdown selectors. The answer will be something like:
$(function() {
$('.agefrom_selection').change(function () {
var quantity_1 = parseInt($('.agefrom_selection').val());
var quantity_2 = parseInt($('.ageto_selection').val());
if ( quantity_1 > quantity_2 ) {
$('.age_warning').addClass('show_age_warning')
}
else {
$('.age_warning').removeClass('show_age_warning')
}
});
$('.ageto_selection').change(function () {
var quantity_1 = parseInt($('.agefrom_selection').val());
var quantity_2 = parseInt($('.ageto_selection').val());
if ( quantity_1 > quantity_2 ) {
$('.age_warning').addClass('show_age_warning')
}
else {
$('.age_warning').removeClass('show_age_warning')
}
});
If anybody else can come up with something better, I am very willing to listen. Thanks
I try to develop a custom selectbox with „chosen“ (https://harvesthq.github.io/chosen/).
How can I achieve to add a single input text field ("Eigene Auflage") at the bottom of the opened select box which adds his value to the top, if someone clicks at it types something in. See image: )
Do I have to change the select/option into a ul/li ?
Here is my markup:
<select class="replace-select">
<option value="select-filled-1">Select Filled 1</option>
<option value="select-filled-2">Select Filled 2</option>
<option value="select-filled-3">Select Filled 3</option>
<option value="select-filled-4">Select Filled 4</option>
<option value="select-filled-5">Select Filled 5</option>
<option value="select-filled-6">Select Filled 6</option>
<option value="select-filled-7">Select Filled 7</option>
<option value="select-filled-8">Select Filled 8</option>
</select>
You can do this just by appending a text box to the chosen's created dropdown div, with events to add the contents of the text box to the original select. It's pretty much just a matter of using jQuery to append the box to the right element.
How it works is when you initialize chosen, it hides the select and creates a custom set of nested li's within a few divs. The dropdown div has class .chosen-drop, so you just need to use jQuery to select that element with $(".chosen-drop"), then append the text box to that using $.append(...). Your event handlers then just need to take the contents of that text box and add it to the original select.
$(document).ready(function() {
//initialize the chosen.
$("#chosenSelect").chosen({
width: "100px"
});
//append text box
$("#selectContainer .chosen-drop").append('<input class = "chosen-input"/>');
//click event for enter key
$('.chosen-input').bind("enterKey", function(e) {
//get value of text box, and add it to the select.
var newValue = $(".chosen-input").val();
//insert newValue into an option HTML with template literals
var optionHTML =`<option value="${newValue}">${newValue}</option>`;
$("#chosenSelect").prepend(optionHTML).trigger("chosen:updated");
//clear the textbox after adding to the select
$(".chosen-input").val("");
});
//watch for enter key
$('.chosen-input').keyup(function(e) {
if (e.keyCode == 13) {
$(this).trigger("enterKey");
}
});
});
.chosen-input {
width: 100%
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://harvesthq.github.io/chosen/chosen.jquery.js"></script>
<link href="https://harvesthq.github.io/chosen/chosen.css" rel="stylesheet" />
<div id="selectContainer">
<label>Press enter to add new item to select</label>
<br>
<select id="chosenSelect">
<option value="1">1</option>
<option value="2">2</option>
<option value="3">3</option>
<option value="4">4</option>
</select>
</div>
Let me know if you need an explanation of any elements in my example.
I'm trying to get the value every time the user changes the select component. But the value always returns 'undefined'.
I've been through all Stackoverflow questions and other sites, but without success. I feel like I'm missing something here.
I'm using Ember 2.8.
My component template:
<div class="form-group">
<label for="{{selectId}}">{{selectTitle}}</label>
<select name="{{selectId}}" id="{{selectId}}" class="form-control" {{action "getSelectValue" on="change" value="target.value"}}>
<option value="0" selected>{{selectDefault}}</option>
{{#each model as |choice|}}
<option value={{choice.id}}>{{choice.name}}</option>
{{/each}}
</select>
</div>
My component logic:
import Ember from 'ember';
export default Ember.Component.extend({
tagName: '',
currentValue: null,
actions: {
getSelectValue(value) {
console.log(value); //always returns undefined
}
}
});
I'm calling it like this:
{{select-control model=model.tasks selectTitle="Task" selectDefault="Choose Task" selectId="taskSelect"}}
In the template I've also used the onchange="{{action...}}" syntax, but then the action wasn't called.
At this point I have no logic in my route or controller handling this.
Thanks for your help!
<select name="{{selectId}}" id="{{selectId}}" class="form-control" {{action "getSelectValue" on="change" value="target.value"}}>
change the above line to
<select name="{{selectId}}" id="{{selectId}}" class="form-control" onchange={{action "getSelectValue" value="target.value"}}>
I have a form with different selects like :
<select [(ngModel)]="selected.isConnected" (ngModelChange)="formChanged()" name="etat" id="etat" class="form-control">
<option value="0">Not connected</option>
<option value="1">Connected</option>
</select>
My backend expect to receive an int in the "isConnected" attribute. Unfortunately as soon as I change the value of the select the attribute is cast to a string :
{
isConnected : "0", // 0 expected
}
For standard <input> I could use type="number" but for a <select> I'm clueless.
Is there a way to force angular 2 to cast the data to int ?
Use [ngValue] instead of "value":
<select [(ngModel)]="selected.isConnected" id="etat">
<option [ngValue]="0">Not connected</option>
<option [ngValue]="1">Connected</option>
</select>
If you want cast it within formChanged() method (Which you haven't provided yet).
You should use + symbol as shown below,
formChanged(): void {
selected.isConnected = +selected.isConnected;
...
}
No, sadly you're forced to parse it on your own in the formChanged() method, since you always get a string back from the select.
You could try it with something like this:
formChanged(): void {
selected.isConnected = parseInt(selected.isConnected);
// ...
}
You can send a Number variable to select and assign the value for that select element. Then if you want to capture the value when it changes, you can add (change) event to select and retrieve the value as shown below.
import { Component } from '#angular/core';
#Component({
selector: 'my-app',
template: `<select value="{{isConnected}}" (change)="printConnected($event.target.value)" name="etat" id="etat" class="form-control">
<option value="0">Not connected</option>
<option value="1">Connected</option>
</select>
<div *ngIf="changed">You've selected {{isConnected}}<div>`
})
export class AppComponent {
isConnected : number = 1;
changed : boolean = false;
printConnected(value){
this.isConnected = value;
this.changed=true;
}
}
You can view an example at http://plnkr.co/edit/xO2mrTdpTGufkgXqdhYD?p=preview
I am using reactive bindings and do not want to use [(ngModel)]. Instead I created a piped observable that uses JSON.parse(value) (because +value doesn't handle "null"):
*.component.html:
<div class="col-lg-4 form-group">
<label>Group Type</label>
<select class="form-control" (change)="groupType$.next($event.target.value)">
<option [value]="null"></option>
<option *ngFor="let groupType of filterData.groupTypes" [value]="groupType.id">{{groupType.label}}</option>
</select>
</div>
<div class="col-lg-4 form-group" *ngIf="filteredGroups$ | async as groupOptions">
<label>Group</label>
<select class="form-control" (change)="group$.next($event.target.value)">
<option [value]="null"></option>
<option *ngFor="let group of groupOptions" [value]="group.id">{{group.label}}</option>
</select>
</div>
<div class="col-lg-4 form-group">
<label>Status</label>
<select class="form-control" (change)="status$.next($event.target.value)">
<option [value]="null"></option>
<option *ngFor="let status of filterData.statuses" [value]="status.id">{{status.label}}</option>
</select>
</div>
*.component.ts:
group$ = new BehaviorSubject<string>(null);
groupId$ = this.group$.pipe(
map((groupId: string) => JSON.parse(groupId) as number)
);
groupType$ = new BehaviorSubject<string>(null);
groupTypeId$ = this.groupType$.pipe(
map((typeId: string) => JSON.parse(typeId) as number)
);
status$ = new BehaviorSubject<string>(null);
statusId$ = this.status$.pipe(
map((statusId: string) => JSON.parse(statusId) as number)
);
[ngValue] is intended for objects. It generates an artificial option value even for numeric constants. For those who might be concerned about tests or readability, you can expand two way binding microsyntax
<select [ngModel]="selected.isConnected"
(ngModelChange)="selected.isConnected=$event && +$event" id="etat">
<option value="0">Not connected</option>
<option value="1">Connected</option>
</select>
I am trying to get the form id when an option in a drop down is selected:
HTML
<form id="test">
<select id="option1">
<option id="opt1">Hello</option>
</select>
</form>
JS:
$("#test").change(function(){
var formid=$("test").parent("form");
alert(formid);
});
The output in the alert is "object object". I have also tried closest which gives the same output.
$("#test").change(function(){
var formid=$("test").parent("form").attr('id');
alert(formid);
});