Angular empty option remove - javascript

I have problem with empty option when i repeat through array.
Here is code.
View:
<select ng-model="getseason" class="form-control">
<option ng-repeat="season in seasons" value="{{ season }}">
Season {{ season + '/' + seasonaddone(season) }}
</option>
</select>
Model:
$scope.getseason={};
$scope.seasons = [2014,2013,2012,2011,2010,2009,2008,2007,2006,2005];
$scope.getseason = $scope.seasons[0];
$scope.seasonaddone = function(season){
return ++season;
}
$scope.$watch('getseason',function(){
console.log($scope.getseason);
console.log(typeof $scope.getseason);
});
How can i remove empty option?
I find many similiar problems, but i cant find solution for this.

Try to use ngOptions instead of ngRepeat
Try like this
<select ng-model="getseason" class="form-control" ng-options="season as 'Season '+ season + '/' + seasonaddone(season) for season in seasons">
</select>

Related

Angular JS Error: [ngRepeat:dupes] Duplicates in a repeater are not allowed

I am facing an issue of [ngRepeat:dupes].
systemService.getAllSystemSettings().then(
function (obj) {
$scope.project.meta.franchise = obj.find(item => item.keyword === "Program");
console.log($scope.project.meta.franchise);
$scope.project.meta.franchise = $scope.project.meta.franchise['keywordValue'].split(';');
console.log($scope.project.meta.franchise);
return $scope.project.meta.franchise);
});
in my HTML page :
<select class="form-control" ng-model="project.meta.franchise" ng-disabled="readOnlyUser">
<option ng-repeat="option in project.meta.franchise" value="{{option}}">{{option}}</option>
</select>
Output in console :
{ keyword: "Program", keywordValue: "test_abc;abc_&xyz;efg_&_hij"
}
[
"test_abc",
"abc_&xyz",
"efg_&_hij"
]
error in console:
Please help me out in solving I tried putting track by $ index but no solution with that too. By using $track by it does not show the list in options. ThankYou in advance.
Try changing the value of the ng-model to project.franchise in your HTML code. Below is the code I applied and it worked for me:-
<select class="form-control" ng-model="project.franchise" ng-disabled="readOnlyUser">
<option ng-repeat="option in project.meta.franchise)" value="{{option}}">{{option}}</option>
</select>
try to make a custom unique index like this
<select class="form-control" ng-model="project.meta.franchise)" ng-disabled="readOnlyUser">
<option ng-repeat="option in project.meta.franchise track by ($index + ':' + option)" value="{{option}}">{{option}}</option>
</select>
Try giving multiple = 'true' in your HTML select statement. Please refer to Davis Ford's post in GitHub regarding the same.

AngularJS variable not updating in view

A question that has been asked (and answered) a thousand times, yet I can't figure this out.
I'm trying to update the option labels of a select box based on the value of another.
Select code for the source of the new label:
<select id="year" name="year" ng-model="Data.year" ng-change="updateAge(Data.year)">
Option value code for the target of the new label
<option value="low">{{ Age.low }}</option>
Controller code to update the scope variable. The second console log displays the updated age, but that isn't shown in the view. I've tried $scope.$apply() but Angular errors because $apply is already in progress.
$scope.updateAge = function( year ) {
if ( year == '2016' ) {
console.log($scope.Age.low);
$scope.Age.low = 'NEW AGE';
console.log($scope.Age.low);
}
}
Some observations :
As you set the option value as "low". Hence, on updateAge function call this block if ( year == '2016' ) { ... } will not execute because year value will always be low.
Make option value also dynamic.
try <option value="{{ Age.low }}">{{ Age.low }}</option>
instead of <option value="low">{{ Age.low }}</option>
DEMO
var myApp = angular.module('myApp',[]);
myApp.controller('MyCtrl', function($scope) {
$scope.Age = {"low": '2016'};
$scope.updateAge = function(year) {
if (year == '2016') {
console.log($scope.Age.low);
$scope.Age.low = 'NEW AGE';
console.log($scope.Age.low);
}
}
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="myApp" ng-controller="MyCtrl">
<select id="year" name="year" ng-model="Data.year" ng-change="updateAge(Data.year)">
<option value="{{ Age.low }}">{{ Age.low }}</option>
</select>
</div>

Get values selected from SelectBox Angularjs

I'm new to Angularjs and I have selectBox with two variables (startDate and endDate):
<div>
<select class="form-control" ng-model="date.time">
<option ng-repeat="time in dateList" value="{{time.startDate}},{{time.endDate}}" >
{{time.startDate| date:'medium'}} - {{time.endDate | date:'medium'}}</option>
</select>
</div>
After the user select a period I want to get the startDate and endDate separately.
Did you try looking at what your value holds when you're done selecting? You'll get the string you put inside the option's value.
var dates = $scope.date.time.split(','),
startDate = dates[0],
endDate = dates[1];
With the ng-options syntax you can set to your date.time the whole object:
<select class="form-control" ng-model="date.time" ng-options="time as ((time.startDate | date:'medium') + ' - ' + (time.endDate | date:'medium')) for time in dateList"></select>
What ever you have bound in your ng-model will hold the selected value.
In your case the ng-model is holding date.time, which may not be what you are looking for.
Additionally you should set the value to be the data that you wish to extract from the option list.
Please see this (poorly and quickly constructed) jsFiddle
html
<div ng-controller="MyCtrl">
<select class="form-control" ng-model="selected">
<option ng-repeat="time in dateList" value="{{time}}" >
{{time.prop}}</option>
</select>
{{selected}}
</div>
js
var myApp = angular.module('myApp',[]);
//myApp.directive('myDirective', function() {});
//myApp.factory('myService', function() {});
function MyCtrl($scope) {
$scope.selected = 'plz select a thing';
$scope.dateList = [{prop:'prop1'}, {prop:'prop2'}];
}

Can't remove blank select <option> created by ng-repeat in AngularJS

This is a common problem however when trying to use the solutions provided here on Stackoverflow I am having no success... I have the following in my HTML view:
<select class="date-input" ng-model="reservation.date">
<option ng-repeat="d in dates track by $index"
value="{{ d }}"
> {{ d }} </option>
</select>
In my controller I have the following...
$scope.makeDates = (function () {
dArray =[];
// we make a big array of dates ['dd-mm-yyyy','dd-mm-yyyy', 'dd-mm-yyyy'...] for 3 months and return it
return dArray;
}();
$scope.reservation = {
date : null,
time : null,
quantity : null
};
$scope.dates = $scope.makeDates;
$scope.reservation.date = $scope.dates[0];
However despite me setting $scope.reservation.date = $scope.dates[0]; the select still produces a blank option and is the default/selected value!?!?! Am I missing something? I know it is early but I can't see what I am doing wrong?
You don't need attribute value="{{ d }}" for <option>. This is a reason why you get empty item.
HTML
<div ng-app='myApp' ng-controller="ArrayController">
<select class="date-input" ng-model="reservation.date">
<option ng-repeat="d in dates track by $index">{{d}}</option>
</select>
</div>
Demo Fiddle

How to set selected select option in Handlebars template

With a Handlebars.js template like this...
<select>
<option value="Completed">Completed</option>
<option value="OverDue">OverDue</option>
<option value="SentToPayer">SentToPayer</option>
<option value="None">None</option>
</select>
... and data like this...
{
"id" : 1,
"name" : "World"
"status" : "OverDue",
"date" : "2012-12-21"
}
I want to render HTML like this.
<select>
<option value="Completed">Completed</option>
<option value="OverDue" selected="selected">OverDue</option>
<option value="SentToPayer">SentToPayer</option>
<option value="None">None</option>
</select>
Which way is the easiest?
I found a lot of over complicated solutions and decided to write my own using a Handlebars helper.
With this partial (using Jquery) ...
window.Handlebars.registerHelper('select', function( value, options ){
var $el = $('<select />').html( options.fn(this) );
$el.find('[value="' + value + '"]').attr({'selected':'selected'});
return $el.html();
});
You can wrap selects in your Handlebars template with {{#select status}}...
<select>
{{#select status}}
<option value="Completed">Completed</option>
<option value="OverDue">OverDue</option>
<option value="SentToPayer">SentToPayer</option>
<option value="None">None</option>
{{/select}}
</select>
and end up with this...
<select>
<option value="Completed">Completed</option>
<option value="OverDue" selected="selected">OverDue</option>
<option value="SentToPayer">SentToPayer</option>
<option value="None">None</option>
</select>
Presto!
I just had a similar need as the OP--with a static set of select options, but a dynamic selected value. I really like #janjarfalk's solution, but I'm using node.js and don't have jQuery pulled in. So, I put together my own variation based on RegExp's. Hope this is helpful to others.
Handlebars helper:
hbs.registerHelper('select', function(selected, options) {
return options.fn(this).replace(
new RegExp(' value=\"' + selected + '\"'),
'$& selected="selected"');
});
Handlebars template:
<select>
{{#select CurrentSort}}
<option value="1">Most Recent First</option>
<option value="2">Most Recent Last</option>
<option value="3">Highest Score First</option>
<option value="4">Highest Score Last</option>
<option value="5">Most Comments</option>
<option value="6">Fewest Comments</option>
<option value="7">Most Helpful Votes</option>
<option value="8">Fewest Helpful Votes</option>
{{/select}}
</select>
You can tweak the helper to work even if you don't use the value attribute--just adjust the regexp to search the element text, and do the string replacement before the matched text.
I saw the extremely clever solution posted by #janjarfalk and realized it didn't work for options defined without a value attribute (such as <option>Value</option>). My application needed that, and I wanted a helper done in vanilla JavaScript for performance, so I came up with the following.
This solution will support <option>Both a label and a value</option> in addition to <option value="aValue">A label</option> and will be much faster as it doesn't use jQuery.
Handlebars.registerHelper('select', function(value, options) {
// Create a select element
var select = document.createElement('select');
// Populate it with the option HTML
select.innerHTML = options.fn(this);
// Set the value
select.value = value;
// Find the selected node, if it exists, add the selected attribute to it
if (select.children[select.selectedIndex])
select.children[select.selectedIndex].setAttribute('selected', 'selected');
return select.innerHTML;
});
Usage:
<select>
{{#select status}}
<option>Option 1</option>
<option>Option 2</option>
<option value="Option 3">Option 3 (extra info)</option>
<option value="Option 4">Option 4 (more extra)</option>
{{/select}}
</select>
Works for me
<select>
<option value="{{status}}" hidden="hidden" selected="selected">{{status}}</option>
<option value="Completed">Completed</option>
<option value="OverDue">OverDue</option>
<option value="SentToPayer">SentToPayer</option>
<option value="None">None</option>
</select>
I've had problems with the "select block" approach when using the "each" helper to build something dynamic, due to the context.
Here is my solution:
Handlebars.registerHelper('option', function(value, label, selectedValue) {
var selectedProperty = value == selectedValue ? 'selected="selected"' : '';
return new Handlebars.SafeString('<option value="' + value + '"' + selectedProperty + '>' + label + "</option>");
});
And the template:
<select>
{{#each status}}
{{option id name ../statusId}}
{{/each}}
</select>
Improved answer of #lazd to select first option when nothing matches.
Handlebars.registerHelper('select', function(value, options) {
// Create a select element
var select = document.createElement('select');
// Populate it with the option HTML
$(select).html(options.fn(this));
//below statement doesn't work in IE9 so used the above one
//select.innerHTML = options.fn(this);
// Set the value
select.value = value;
// Find the selected node, if it exists, add the selected attribute to it
if (select.children[select.selectedIndex]) {
select.children[select.selectedIndex].setAttribute('selected', 'selected');
} else { //select first option if that exists
if (select.children[0]) {
select.children[0].setAttribute('selected', 'selected');
}
}
return select.innerHTML;
});
Usage remains same:
<select>
{{#select status}}
<option>Option 1</option>
<option>Option 2</option>
<option value="Option 3">Option 3 (extra info)</option>
<option value="Option 4">Option 4 (more extra)</option>
{{/select}}
</select>
This might take more code in the template, but it is easier to read:
.js
Handlebars.registerHelper('select', function(selected, option) {
return (selected == option) ? 'selected="selected"' : '';
});
.hbs
<select name="status">
<option value="public" {{{select story.status 'public'}}}>Public</option>
<option value="private" {{{select story.status 'private'}}}>Private</option>
<option value="unpublished" {{{select story.status 'unpublished'}}}>Unpublished</option>
</select>
I prefer to use a template approach. By this I mean the layout of the option tag itself is specified in the handlebars template (where someone might look for it) and not in the javascript helper. Template inside the block helper is passed into the helper script and can be used by calling options.fn() which then uses any script changes you have made in your helper.
Template:
<select>
{{#optionsList aStatusList sCurrentStatusCode 'statusCode'}}
<option {{isSelected}} value="{{statusCode}}">{{statusName}}</option>
{{/optionsList}}
</select>
Slightly modified data (not required but a little more "real world" for me)
var myOrder =
{
"id" : 1,
"name" : "World",
"statusName" : "OverDue", /* status should NOT be here! */
"statusCode" : "1",
"date" : "2012-12-21"
}
var sCurrentStatusCode = myOrder.statusCode;
var aStatusList =
[
{
"statusName" : "Node",
"statusCode" : 0
},
{
"statusName" : "Overdue",
"statusCode" : 1
},
{
"statusName" : "Completed",
"statusCode" : 2
},
{
"statusName" : "Sent to Payer",
"statusCode" : 3
}
]
Javascript registered helper:
Handlebars.registerHelper( 'optionsList',
function ( aOptions, sSelectedOptionValue, sOptionProperty, options )
{
var out = "";
for ( var i = 0, l = aOptions.length; i < l; i++ )
{
aOptions[ i ].isSelected = '';
if( ( sOptionProperty != null && sSelectedOptionValue == aOptions[ i ][ sOptionProperty ] ) || ( sSelectedOptionValue == aOptions[ i ] ) )
{
aOptions[ i ].isSelected = ' selected="selected" ';
}
out = out + options.fn( aOptions[ i ] );
}
return out;
} );
optionsList is what I have chosen to name this helper
aStatusList an array of status objects contain several properties including the status value/name (in most cases I have encountered this would be the status code not the status name that is stored )
sCurrentStatus is the previously selected status code (not the value) and is the option value that i would like to have the selected in this generated option list.
statusCode is the string property name within a aStatusList object that I will test to see if it matches myStatus that is aStutusList[ loopIndex ][statusCode]
the string option property ( statusCode in this case ) is only required for objects -- options lists may also be arrays of strings (instead of objects that in turn containing strings) in which case you may omit the the third property 'statusCode' which tells the helper what property of the object to test agains. If you don't pass that property it will just test againts the list item itself.
if the sSelectedOptionValue is not passed then the list will be produced without setting any item to selected. This will generate the list pretty much the same as using the {{#each}} helper
I just ran into this problem, here's a solution for when the options are dynamic..
Instead of creating a select helper, I created an option helper that accepts the value of the item you wish to be selected.
Handlebars.registerHelper('option', function(value) {
var selected = value.toLowerCase() === (this.toString()).toLowerCase() ? 'selected="selected"' : '';
return '<option value="' + this + '" ' + selected + '>' + this + '</option>';
});
And in my template.
{{#items}}
{{{option ../selected_value}}}
{{/items}}
Please note the ../ to access the parent's scope as it's not likely the selected_value will be inside of the items array.
Cheers.
If you have very few options and you don't want to write a helper, here is what you can do:
//app.js
var data = {selectedVal: 'b'};
// can also use switch ... case ...
if (data.selectedVal === 'a') {
data.optionASelected = true;
} else if (data.selectedVal === 'b') {
data.optionBSelected = true;
}
// assuming you have a template function to handle this data
templateFunc(data);
In your template file:
<!-- template.html -->
<select id="select-wo-helper" >
<option value="a" {{#if optionASelected}} selected {{/if}}>A</option>
<option value="b" {{#if optionBSelected}} selected {{/if}}>B</option>
</select>
Again this may NOT be the best solution of all, but it probably is a very quick work around when you are dealing very few options and wanted a quick fix.
Today I was also facing the same problem I'm creating a Content Management System and to fetch the status of the post I stuck and in searching for a solution, I landed on this page I found a few answers relevant Because I'm using server-side data and when I used document.createElement it is throwing error document is not defined.
The Regex solution worked for me but I want an easy to understand one whether it is verbose so I came with this solution.
Handlebars.registerHelper('getValue', function(value, options) {
if(options.fn(this).indexOf(value) >= 1){
return `selected='selected'`;
}
});
in the template use the code in this way
<select name="post-status" id="post-status">
<option {{#getValue posts.postStatus}} value="Draft" {{/getValue}} >Draft</option>
<option {{#getValue posts.postStatus}} value="private" {{/getValue}} >private</option>
<option {{#getValue posts.postStatus}} value="publish" {{/getValue}} >publish</option>
</select>
If I'm wrong somewhere Please correct me.
Data source
selectedValue: "8",
option:[
{id_sub_proyectop: "8", clave: "021", name: "Cliclismo"},
{id_sub_proyectop: "9", clave: "022", name: "Atletismo"},
],
helper
Handlebars.registerHelper('selected', function(value, prop) {
if (value === undefined){ return '';};
return value === this[prop] ? 'selected="selected"' : '';
});
Template
<div class="medium-6 cell">
<label>Sub Proyecto / Proceso:
<select name="id_sub_proyectop" required>
{{#each option}}
<option value="{{id_sub_proyectop}}" {{{selected ../selectedValue 'id_sub_proyectop'}}}>{{clave}} - {{name}}</option>
{{/each}}
</select>
</label>
</div>
It should be mentioned that if you do not care about repeats... you can just use vanilla handlebars and place the selected option first, such as:
<select name="ingredient">
<option value="{{ingredient.id}}" selected>{{ingredient.name}}</option>
{{#each ingredients}}
<option value="{{this.id}}">{{this.name}}</option>
{{/each}}
</select>
#lazd's answer does not work for <option> elements within an <optgroup>.
selectedIndex is numbered monotonically for all <option>s, but select.children holds the <optgroup>s, and select.children[n].children holds the <option>s within <optgroup> n (with numbering restarting within each <optgroup>, of course).
This alternative version will work for <option> elements within <optgroup>s:
Handlebars.registerHelper('select-optgrp', function(value, options) {
var select = document.createElement('select'); // create a select element
select.innerHTML = options.fn(this); // populate it with the option HTML
select.value = value; // set the value
var g = 0, i = select.selectedIndex; // calculate which index of which optgroup
while (i >= select.children[g].children.length) { i -= select.children[g].children.length; g++; }
if (select.children[g].children[i]) { // if selected node exists add 'selected' attribute
select.children[g].children[i].setAttribute('selected', true);
}
return select.innerHTML;
});
Another one solution using express-handlebars and dynamic options is this.
Helper function (From all options takes the one we want and change it to selected).
select: function(selected, options) {
return options.fn(this)
.replace( new RegExp(' value=\"' + selected + '\"'), '$& selected="selected"')
.replace( new RegExp('>' + selected + '</option>'), ' selected="selected"$&');
}
handlebars file (I just use #each inside select to receive me data and worked like a charm).
<select name="justAname">
{{#select content.campusId}}
{{#each campus}}
<option value="{{id}}">{{name}}</option>
{{/each}}
{{/select}}
</select>
Handlebars.registerHelper('select', function( value, options ){
return options.fn(this)
.replace( new RegExp(' value=\"' + value + '\"'), '$& selected="selected"')
.replace( new RegExp('>' + value + '</option>'), ' selected="selected"$&');
});
user.country from db session
country stored in country.json file
<select id="country" name="country" class="form-control">
<option value="" selected="selected">(please select a country)</option>
{{#select user.country}}
{{#each countries as |value key| }}
<option value="{{ value.code }}">{{ value.name }}</option>
{{/each}}
{{/select}}
</select>
I know this does not answer the question directly, but in this situation, I passed the unselected html options to the template, and after it is rendered, I use jquery to
mark as selected the value that the json object indicates
for arrays
function select(selected, options) {
return options.fn(this).replace( new RegExp(' value=\"' + selected + '\"'), '$& selected="selected"').replace( new RegExp('>' + selected + '</option>'), ' selected="selected"$&');
},

Categories