How do I add leading spaces into the <select> options using Angular ng-options?
<div ng-controller="MyCntrl">
Static values (works)
<select>
<option value="black">black</option>
<option value="white"> white</option>
<option value="red"> red</option>
<option value="blue"> blue</option>
<option value="yellow"> yellow</option>
</select>
Values from JS using angular (only the first-default works)
<select ng-model="color" ng-options="c.name for c in colors">
<option value=""> default</option>
</select>
</div>
JS:
angular.module("myApp", []).
controller("MyCntrl", ['$scope', function ($scope) {
$scope.colors = [{
name: 'black',
shade: 'dark'
}, {
name: ' white',
shade: 'light'
}, {
name: ' red',
shade: 'dark'
}, {
name: ' blue',
shade: 'dark'
}, {
name: ' yellow', // spaces here
shade: 'light'
}];
}]);
you can format the option text:
<select ng-model="color" ng-options="(' '+c.name) for c in colors">
<option value=""> default</option>
</select>
EDIT
If you want to generate the dynamically it is a little bit more complicated. Suppose you have a function in your controller that knows how many you want to add, then you can write this function like this:
$scope.addSpaces= function(color){
var count = 1;// put your logic here
var result = "";
for(var i=0; i<count; i++){
result+= String.fromCharCode(160);
}
return result;
};
in your html it will be:
<select ng-model="color" ng-options="(addSpaces(c)+c.name) for c in colors">
<option value=""> default</option>
</select>
This works because we concatenate the unicode character for (e.g. ) in our string and not the entity, so there is nothing to escape for the element.text() function.
Related
This is my current setup:
HTML
<question
v-for="question in questions"
v-bind:id="question.id"
v-bind:title="question.title"
v-bind:statement="question.statement"
v-bind:interaction="question.interaction"
#onchange-vg="onChangeVg"/>
</question>
Definition of <question>
var questionComponent = Vue.component('question', {
props: ['id', 'title', 'statement', 'interaction', 'currentQuestion'],
template: `
<div :id="'question-' + id">
<div class="flex my-3">
<div class="py-0"><span>{{ id }}</span></div>
<div>
<p>{{ title }}</p>
<div :class="{'hidden':(id !== this.$parent.currentQuestion), 'block':(id === this.$parent.currentQuestion)}">
<p>{{ statement }}</p>
<span v-html="interaction"></span>
</div>
</div>
</div>
</div>
`
});
Vue
var app = new Vue({
el: '#app',
data() {
return {
vg: null,
currentQuestion: 1,
questions: [
{
id: 1,
title: 'Question 1',
statement: 'Details for question 1',
interaction: `
<select ref="vb-art" #change="$emit('onchange-vg')">
<option disabled value="" selected>Make a choice</option>
<option value="red">Red</option>
<option value="blue">Blue</option>
</select>
`
},
{
title: 'Question 2',
statement: 'Details for question 2',
interaction: `
<select ref="vb-art" #change="$emit('onchange-vg')">
<option disabled value="" selected>Make a choice</option>
<option value="black">Black</option>
<option value="white">White</option>
</select>
`
},
],
}
},
methods: {
onChangeVerguetungsart() {
console.log("Value: " + event.target.value);
currentQuestion++;
},
},
});
Everything is rendered fine. My problem is, that the event handler #change in <select ref="vb-art" #change="$emit('onchange-vg')"> does not fire.
Whe I replace <span v-html="interaction"></span> whit the whole <select ref="vb-art" #change="$emit('onchange-vg')">...</select> code from interaction every thing works fine.
The interactions may be different from question to question. It could be an , a or just a simple link. That's why i try to put the code into the array and not to the component definition.
How can I solve this issue, so that <span v-html="interaction"></span> accepts the event handler from a code snippet that is delivered by an array value?
You should avoid v-html. v-html bind just plain HTML, not Vue directives.
For you case v-html is not necessary. Make array of options from interaction property and generate your markup by vue template.
interaction: [
{value: 'red', label: 'Red'},
{value: 'blue', label: 'Blue'}
]
and in your component
<select ref="vb-art" #change="$emit('onchange-vg')">
<option disabled value="" selected>Make a choice</option>
<option v-for="{value, label} in interaction" :key="value" :value="value">{{ label }}</option>
</select>
update:
IF you have dynamic content, then slot is your friend. (Refer docs
https://v2.vuejs.org/v2/guide/components-slots.html for more examples)
Your component:
<div>
<p>{{ title }}</p>
<div>
<p>{{ statement }}</p>
<slot />
</div>
</div>
And usage
<question
v-for="question in questions"
v-bind:id="question.id"
v-bind:title="question.title"
v-bind:statement="question.statement"
v-bind:interaction="question.interaction"
>
<select ref="vb-art" #change="onChangeVg">
<option disabled value="" selected>Make a choice</option>
<option value="red">Red</option>
<option value="blue">Blue</option>
</select>
</question>
Bonus is, that you don't need to emit anything.
Btw using this.$parent is also not qood idea. Your component is coupled with parent. Use props instead.
I has made a ng-repeat of all users but what i want is that he selected current user
<select id="taskUser" class="form-control"
multiple="multiple"
ng-model="taskUser"
ng-options="user.ID as user.Name for user in header.users"
>
</select>
This is my repeater and i show how te list is look like:
<select id="taskUser" class="form-control ng-pristine ng-untouched ng-valid ng-empty" multiple="multiple" ng-model="taskUser" ng-init=" users = header.users[2].id" ng-options="user.ID as user.Name for user in header.users">
<option label="User 1" value="string:1">User 1</option>
<option label="User 2" value="string:2">User 2</option>
<option label="User 3" value="string:3">User 3</option>
</select>
To get the current user id i used {{header.user.ID}} than i get the result just: 3
That means that this need to be selected
<option label="User 3" value="string:3">User 3</option>
$scope.taskUser should be list and defined as [3] because you use multiple
Fiddle Demo
Full code:
function MyCtrl($scope, $timeout) {
$scope.header = {
users:[
{ID: 1, Name: "AAA"},
{ID: 2, Name: "BBB"},
{ID: 3, Name: "CCC"}
]
};
$scope.taskUser = [3];
}
HTML
<select id="taskUser" class="form-control"
multiple="multiple"
ng-model="taskUser"
ng-options="user.ID as user.Name for user in header.users"
>
</select>
<pre>taskUser: {{taskUser|json}}</pre>
You need to define the selected value in an array $scope.taskUser = [3];
var myapp = angular.module('myapp', []);
myapp.controller('FirstCtrl', function ($scope) {
$scope.header = {};
$scope.header.users = [
{ ID: 1, Name: 'John' },
{ ID: 2, Name: 'Rocky' },
{ ID: 3, Name: 'John'},
{ ID: 4, Name: 'Ben' }
];
$scope.taskUser = [3];
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="myapp">
<fieldset ng-controller="FirstCtrl">
<select id="taskUser" class="form-control"
multiple="multiple"
ng-model="taskUser"
ng-options="user.ID as user.Name for user in header.users"
></select>
</fieldset>
</div>
I have the following ng-repeat:
<select class="action-dropdown fade" ng-model="item_value">
<option value="" disabled>Choose an Step</option>
<option ng-repeat="step in steps | orderBy:'+step_number'" ng-if="step.step_number >= active_step" value="{{$index}}">Step {{step.step_number}}</option>
</select>
I am attempting to change this to an ng-option because the following option is popping up and I think this might fix the issue:
<option value="? string:5 ?"></option>
I'm trying to wrap my head around how to include my ng-if statement with the ng-option and to use the word Step $index when displaying the option.
The comprehension expressions are just blowing my mind and I was wondering if anyone could help me out.
This is what I have so far:
<select class="action-dropdown fade" ng-model="item_value" ng-options="$index as step.step_number for step in steps" required>
<option value="" disabled>Choose a Step</option>
</select>
look the snipped as I've commented
I think that the best way (cleaner way) is populate the steps list on change active_step. To access the index you can use the (key,value) syntax
select as label for (key , value) in object
Doc: https://docs.angularjs.org/api/ng/directive/ngOptions
angular.module('app', [])
.controller('DefaultController', function () {
this.item_value = null;
this.steps = [
{ step_number: 5 },
{ step_number: 2 },
{ step_number: 6 },
{ step_number: 3 },
{ step_number: 1 },
{ step_number: 4 },
]
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="app">
<div data-ng-controller="DefaultController as ctrl">
<select ng-model="ctrl.item_value" ng-options="step as 'Step ' + index for (index, step) in ctrl.steps | orderBy:'+step_number'" required>
<option value="" disabled>Choose a Step</option>
</select>
Selected: {{ ctrl.item_value }}
</div>
</div>
EDIT: Using only ng-options as much as possible.
How the data looks like:
vm.category = [
0: {
label: 'Label A',
children: [
{
label: 'Label A.1',
value: 'labelA1',
}
]
}
1: {},
2: {}
]
How it will look like in the HTML. Expected HTML
<select>
<optionGroup> Label A </optionGroup>
<option value="labelA1"> Label A.1 </option>
<option value="labelA2"> Label A.2 </option>
<optionGroup> Label B </optionGroup>
<option value="labelB1"> Label B.1 </option>
</select>
How to achieve this without changing the data structure as much as possible?
I tried ng-options="category.children.label group by category.label for category in vm.categoryTree". But the output is
<select>
<optionGroup> Label A </optionGroup>
<option> undefined </option>
<optionGroup> Label B </optionGroup>
<option> undefined </option>
</select>
Easiest way would be to map the data to a format more easily used by the ng-options "group by" expression
angular.module('so', []).controller('snippet', function() {
this.categoru = [{"label":"Label A","children":[{"label":"Label A.1","value":"labelA1"}]},{"label":"Label B","children":[{"label":"Label B.1","value":"labelB1"}]}];
this.options = this.categoru.reduce((flat, group) => {
Array.prototype.push.apply(flat, group.children.map(child => {
return Object.assign({
parent: group.label
}, child);
}));
return flat;
}, []);
console.log(this.options);
});
<form ng-app="so" ng-controller="snippet as vm">
<select ng-model="vm.selected"
ng-options="opt.label group by opt.parent for opt in vm.options track by opt.value">
</select>
<pre>vm.selected = {{vm.selected | json }}</pre>
</form>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.8/angular.min.js"></script>
You can do this,
<select ng-model='theModel' ng-change="display(theModel)">
<optgroup ng-repeat='group in collection' label="{{group.Name}}">
<option ng-repeat='veh in group.Fields' value='{{group.Name}}::{{veh.Name}}'>{{veh.Name}}</option>
</optgroup>
</select>
DEMO
i have successfully set up a dependant dropdown using angularjs, but i have a little problem:
i need to define the value of every option tag because it is set up automatically by angular processor.
here is my html code:
<div ng-controller="CountryCntrl">
<select id="country" ng-model="states" ng-options="country for (country, states) in countries">
<option value=''>Choose</option>
</select>
Departement:
<select id="state" ng-disabled="!states">
<option value="">Choose</option>
<option ng-repeat="state in states" value="{{state.id}}">{{state.dep}}</option>
</select>
</div>
<br/>
<input type="submit" value="go">
and here is my angularjs code:
<script>
var Aplic = angular.module("Aplic", []);
Aplic.controller('CountryCntrl', function($scope){
$scope.countries = {
'Aquitaine': [ {'id':'22', 'dep': "Dordogne"}, { 'id':'31', 'dep' : "Gironde"} ],
'Auvergne': [ {'id' : '3', 'dep' : "Allier"}, {'id' : '15', 'dep' : "Cantal"} ]
};
});
</script>
I repeat, i have successfully set up the value for the option in the second dropdown, but for the first one it takes automatically the name of variable country.
so how should i change my code to give every option tag in the first dropdown a specific value.
to understand well my idea, please inspect the values in every dropdown. here is my working snippet on plunker:
http://embed.plnkr.co/VBdxGDQNOJSHeGVfloo2/preview
any help will be appreciated.
here is what i want to do:
<select id="state" ng-model="cou">
<option value="">Choisir</option>
<option ng-repeat="cou in countries" value="{{cou.id}}">{{cou.name}}</option>
</select>
<select id="state" ng-disabled="!cou">
<option value="">Choisir</option>
<option ng-repeat="state in cou.states" value="{{state.id}}">{{state.dep}}</option>
</select>
but now the second dropdown does not work, if you can fiw that the problemwill be solved
Here is sample implementation for you. This will keep values in option tag.
<div ng-app="Aplic" ng-controller="CountryCntrl">
<select id="country" ng-model="selectedCountry" ng-options="country.id as country.name for country in countries track by country.id">
<option value="">Choose</option>
</select>Departement:
<select id="state"
ng-model="selectedState"
ng-disabled="!selectedCountry"
ng-options="state.id as state.dep for state in ((countries | filter:{'id':selectedCountry})[0].states) track by state.id">
<option value="">Choose</option>
</select>
<div>selectedCountry id: {{selectedCountry}}</div>
<div>selectedState id: {{selectedState}}</div>
</div>
Controller:
$scope.countries =[
{
'id': '1',
'name': "Aquitaine",
'states': [{
'id': '22',
'dep': "Dordogne"
}, {
'id': '31',
'dep': "Gironde"
}]
},
{
'id': '2',
'name': "Auvergne",
'states': [{
'id': '3',
'dep': "Allier"
}, {
'id': '15',
'dep': "Cantal"
}]
}];
Working demo