I'm trying to make a menu where I can change the "cell" property of a person. Cells are defined as:
Cells: [
{ name: 'NE', id: 1 },
{ name: 'NW', id: 2 },
{ name: 'SE', id: 3 },
{ name: 'SW', id: 4 }
]
My html code
<div><select ng-model="ui.returnedPeopleList[row.rowIndex]" ng-options="cell for cell in Cells"></select></div>
returnedPeopleList is an array of people. Basically what I have is a grid of people. Double clicking a person opens a modal instance where you can change their properties (hence, the row.rowIndex). The row is passed to the instance modal instance, where the changes are made. I'm not sure how much of this is relevant to the dropdown; I'm pretty new to angular.
The dropdown menu is empty, and I have no idea what's wrong. Thanks in advance.
You need the right syntax for ng-options
ng-options="cell.id as cell.name for cell in Cells"
Will produce the following option elements:
<option value="1">NE</option>
<option value="2">NW</option>
<option value="3">SE</option>
<option value="4">SW</option>
One problem is that you in your ng-options. Your display value is going to be the object in the list, not the object property you want.
Try:
ng-options="cell as cell.name for cell in Cells"
Also make sure Cells is on your $scope.
Below code may help you <div><select ng-model="returnedPeople" ng-options="cell as cell.name for cell in Cells" ng-change="ui.addToPeopleList(returnedPeople)"></select></div>.I think ng-model is not setting the value to ui.returnedPeopleList[row.rowIndex].
Related
I'm new to JavaScript and jQuery. I'm trying to create something for a website I'm working on, but I can't figure this out.
How can I get jquery to show or hide a select option of a dropdown, based on the selected data attribute of another dropdown?
IE, selecting option 2 in the first dropdown will show only options 1 and 3 in the second menu, and vice versa?
$(document).ready(function() {
$("#make_id").change(function() {
/* basically if data-make is = to selected data-id option, show option,
if it isn't, hide this option. seems, simple, but I can't figure it out... */
})
})
<select id="make_id" >
<option value="make option 1" data-id="18">option 1</option>
<option value="make option 2" data-id="42">option 1</option>
</select>
<select id="model_id" >
<option value="model option 1" data-make="42">option 1</option>
<option value="model option 2" data-make="18">option 2</option>
<option value="model option 3" data-make="42">option 3</option>
</select>
$("#make-id").change(function(e){
var currentMake = $("#make-id").data("id");
$("#model-id option").not("[data-make='"+currentMake+"']").hide();
$("#model-id option").filter("[data-make='"+currentMake+"']").show();
}
In English:
Whenever make-id changes, get the data-id field from it.
Select all the options under model-id then filter for ones that don't have the same data-make value. Hide those.
Select all the options under model-id then filter for the ones that do have the same data-make value. Show those.
TL;DR
I've changed the way your code works a little to make it work better for the way you want it to. Take a look at this fiddle.
So first of all, you can easily define a callback on the change event which can filter the second select box's option visibility. One problem you may come into if you do this is that "hidden" options will still be in the select's value if they were previously selected (as in Franz's answer).
Here's a slightly different approach in which everything is emptied and loaded dynamically from a JSON object that you define initially:
1. Define your JSON object (data model)
This could come from a database as well of course.
var makesAndModels = {
"makes": [
{"option_id": 1, "id": 18, "name": "make 1"},
{"option_id": 2, "id": 42, "name": "make 2"}
],
"models": [
{"option_id": 1, "make_id": 42, "name": "make 2: model 1"},
{"option_id": 2, "make_id": 18, "name": "make 1: model 1"},
{"option_id": 3, "make_id": 42, "name": "make 2: model 2"}
]
};
2. Define methods to populate each select
Your rules are simple:
To populate the makes, you need no conditions
To populate the models, you need a make ID (foreign key)
function populateMakes() {
var $make = $('#make_id');
// Remove all options before starting
$make.empty();
// Loop the makes from the JSON data object
$.each(makesAndModels.makes, function(key, make) {
// Append new options for each make
$('#make_id')
.append(
$('<option></option>')
.data('id', make.id) // Assign the data-id attribute
.attr('value', 'make option ' + make.option_id) // Give it a value
.text(make.name) // Give it a label
);
});
}
The function above is simply emptying the #make_id select box, then looping the makes in the JSON data object and appending a new option element to the makes select for each result, setting the attributes as it goes.
Then to populate the models, we do the same thing for models as we did for makes, except we'll ignore any models that are for a different make.
function populateModels(makeId) {
// Assign the selector to a variable to repeated use/Don't Repeat Yourself
var $model = $('#model_id');
// Remove all models in the select to start
$model.empty();
// Loop the models in the JSON object
$.each(makesAndModels.models, function(key, model) {
// Ignore any models for other makes
if (model.make_id != makeId) {
return;
}
// Append the new model to the select
$model
.append(
$('<option></option>')
.data('make', model.make_id) // Assign its data-make attribute
.attr('value', 'model option ' + model.option_id) // Give it a value
.text(model.name) // Give it a label
);
});
}
3. Simplified HTML
Once you've got that framework, your HTML and event handlers are going to be very simple.
The HTML select boxes don't need any options since they're populated dynamically, although you may want to leave the ones you have there already in place to help with older browsers or browsers with Javascript turned off (cringe):
<!-- These are populated dynamically now! -->
<select id="make_id"></select>
<select id="model_id"></select>
4. Create your jQuery event handler
...and glue it all together:
$(document).ready(function() {
// Populate the makes select box
populateMakes();
// Define what should happen when you change the make_id select
$("#make_id").change(function() {
// Find the currently selected make's ID from data-id
var selectedMake = $(this).find('option:selected').data('id');
populateModels(selectedMake);
});
// Trigger a change to populate the models the first time
$('#make_id').change();
});
The trick above is that once you've populated the makes and defined your event handler for when the makes select box changes, you can to trigger the change event manually - this will cause populateModels() to be called with the first make in the list, and have the models for that make populated too.
$(document).ready(function() {
$("#make_id").change(function() {
if ($(this).val()=='make option 2') $("#model_id").find("option").eq(1).hide();
else $("#model_id").find("option").eq(1).show();
})
})
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<select id="make_id" >
<option value="make option 1" data-id="18">option 1</option>
<option value="make option 2" data-id="42">option 2</option>
</select>
<select id="model_id" >
<option value="model option 1" data-make="42">option 1</option>
<option value="model option 2" data-make="18">option 2</option>
<option value="model option 3" data-make="42">option 3</option>
</select>
I have been trying to set the default selected option of the select box, don't know where I'm doing wrong.
here is my html
<span ng-controller="sizeController" style="width:137px; float:left; margin:15px 0 0 10px; ">
<label for="sizeSelect" style="float:left; color:orange">Size:</label>
<select name="sizeSelect" id="colorSelect" style="width:90px" ng-model="size" ng-change ="onSizeChange(size)">
<option ng-repeat="sizeoption in data.sizeOptions" value="{{sizeoption.id}}">{{sizeoption.name }}</option>
</select>
</span>
controller goes here
function sizeController($scope, $rootScope) {
$scope.data = {
sizeOptions: [
{id: 'Small', name: 'Small'},
{id: 'Medium', name: 'Medium'},
{id: 'Large', name: 'Large'},
{id: 'XLarge', name: 'XLarge'}
],
selectedOption: {id: 'Small', name: 'Small'}
};
$scope.onSizeChange = function(size){
$rootScope.size = size;
};
}
By default first value in the select box is always empty.
dont't know why.
thanks in advance
Please do yourself a favor by using ng-options instead of ng-repeating the options yourself.
<select name="sizeSelect"
id="colorSelect"
style="width:90px"
ng-model="size"
ng-change="onSizeChange(size)"
ng-options="sizeoption.id as sizeoption.name for sizeoption in data.sizeOptions">
</select>
Initialize by setting the model directly
$scope.size = "Small";
I make solution for you. Use ng-option for select in angular.
Solution
Here is more about ng-option:
ngOption
The first value in the select box is always empty because it is undefined. The select dropdown (ng-model="size") corresponds to size attribute of model, which is initially undefined. Initialize the size in the scope to one of the possible values like below, it will remove the undefined empty first option.
$scope.size = 'Medium';
But even if you initialize size to 2nd or 3rd option it will still select the first option, now you have to use ng-select to select the correct value ng-selected="size == sizeoption.id"
Complete solution here
I have the following in my view
<div>
<select ng-model="obj.arr[otherObj.variable]" ng-change="otherObj.variable=SOMETHING">
<option ng-repeat="label in obj.arrs">{{label}}</option>
</select>
</div>
Without the ng-change attribute, this code does what I want when otherObj.variable is one of the indexes of the obj.arr - it selects the correct item in the list.
What I want in addition to this is to set otherObj.variable to the index of the array item that is picked when the dropdown variable is changed. So, if the second value in the dropdown is picked then otherObj.variable should be set to 1. I tried to do this with a
ng-change="otherObj.variable=SOMETHING"
Problem is., I don't know what that SOMETHING should be. Am I doing this right?
EDIT
My requirements are
Select the top option in the dropdown by default
select the appropriate item in the array depending on the value of otherObj.variable (this gets set by some external code so if I come to the page with this value set then I want the correct option selected)
Make sure otherObj.variable is updated if I change the value in the dropdown.
angular.module('selects.demo', [])
.controller('SelectCtrl', function($scope){
$scope.values = [{
id: 1,
label: 'aLabel',
}, {
id: 2,
label: 'bLabel',
}];
$scope.selectedval = $scope.values[0];
});
<script src="https://code.angularjs.org/1.3.15/angular.js"></script>
<div ng-app="selects.demo">
<div ng-controller="SelectCtrl">
<p>Using ngOptions without select as:</p>
<select ng-model="selectedval" ng-options="value.label for value in values"></select>
<p>{{selectedval}}</p>
<p>Using ngOptions with select as statement: (this will return just the id in the model)</p>
<select ng-model="selectedval2" ng-options="value.id as value.label for value in values"></select>
<p>{{selectedval2}}</p>
</div>
</div>
Sorry if my comment was a little cryptic. Select elements like other form elements are actually directives in AngularJS, so they do a lot of stuff for you automatically. You don't need to use an ngChange to populate the ngModel associated with your select element. AngularJS will handle that for you.
Also, you can use ngOptions instead of ngRepeat on select elements to generate the values automatically on options.
Assuming that you have an object with values:
$scope.values = [{
id: 1,
label: 'aLabel',
}, {
id: 2,
label: 'bLabel',
}];
You would write:
<select ng-model="selectedval" ng-options="value.label for value in values"></select>
Now your ngModel is going to be bound to the selected element. It will be set with the value of the object that was chosen. If you add {{selectedval.id}} to your view, it will display the id of the selected element.
If you want to set the value to the first item, in your controller, you would add:
$scope.selectedval = $scope.values[0];
If you want to update some property on $scope.values based on the selected value, you could use something like:
$scope.addActiveProp = function() {
var selected = $scope.values.filter(function(e) { return e == $scope.selectedval; });
selected.active = true;
}
And then run the addActiveProp fn in ngChange on the select.
Please give a try with below code
<select ng-model="obj.arr[otherObj.variable]" ng-change="otherObj.variable=key" ng-options="key as value for (key , value) in obj.arrs"></select>
I am facing a problem in AngularJS! (I am very new to AngularJS)
I am trying to setup n select fields with x options and I want to have different ng-model on the select fields.
At the same time I want to disable the option that has been selected in the first select field in all other select fields.
I have tried serveral different things. And the problem was that I could not handle the different models in the ng-repeat
Here is my JSON-File to make things a little bit clearer:
[{
id: 1,
text: "Question1",
selected:false
}, {
id: 2,
text: "Question2",
selected:false
}, {
id: 3,
text: "Question3",
selected:false
}, {
id: 4,
text: "Question4",
selected:false
}, {
id: 5,
text: "Question5",
selected:false
}];
This is one of my attempts. The problem is that the more select fields I have the messier it gets.
I have also found this, but I can't get it to work for my questions in example.
Basically, what I would need to have is something like this:
<select ng-change="onChange()" ng-options='q.value for q in questions | filter:{selected: false}' ng-model='option[$index]'><option value="">-- pick one --</option> </select>
But for some reason the $index is not interpreted as the current index, but as plain string.
You could create an array of question sets. Using ng-repeat you can create multiple drop downs with the same set of initial options.
<div ng-repeat="set in questionSets track by set.id">
<select ng-model="value" ng-options="question.id as question.text for question in set.questions" ng-change="remove($index+1, value);"></select>
<br><br>
</div>
Using ng-change you could pass in the array index of the set of questions. Then you could remove the selected question from all of the other question sets.
$scope.remove = function(key, val) {
_.each($scope.questionSets, function(s) {
if(s.id !== key) {
s.questions = _.reject(s.questions, function(q) {
return q.id=== val;
});
}
})
}
This doesn't handle the case where a user changes the selection multiple times on the first drop down (and multiple options are thus removed from all others), but you can add on to this general idea.
http://plnkr.co/edit/XOTGEc8PfvbUTYIZcL7G?p=preview
I am using knockout.js, and it's not setting the value of an empty option (Four):
<select data-bind="value: item.widgetValue, attr: {id: item.widgetName, name: item.widgetName}, options: item.options, optionsText: ‘label’, optionsValue: ‘value’” id=”fld-“ name=”fld0”>
<option value=”one”>One</option>
<option value=”two”>Two</option>
<option value=”three”>Three</option>
<option value>Four</option>
...
</select>
This is creating a problem: when you're on any option and try to select Four, it selects One; it will only select Four the second time you try to select it.
I have tried changing the knockout data-bind to fix it:
value: $.trim(item.widgetValue)
This allows you to select Four immediately, but incorrectly shows One as being selected after you submit the form with Four selected.
Any ideas as to what could be causing this, or how to fix it?
You shouldn't be manually setting options if you are using the options binding on your select element. If those are being dynamically created by the binding (ie. you are actually using item.options for your source) then check the objects you are binding the select element to -
item.options probably looks like this (missing a value or is somehow not like the other options) -
item.options = [
{ label: 'someLabel1', value: 'someValue1' },
{ label: 'someLabel2', value: 'someValue2' },
{ label: 'someLabel3', 'someValue3' }
];
but should be a more uniform object like this (well defined model) -
function optionModel(label, value) {
var self = this;
self.label = ko.observable(label);
self.value = ko.observable(value);
}
item.options = [
new optionModel('someLabel1', 'someValue1'),
new optionModel('someLabel2', 'someValue2'),
new optionModel('someLabel3', 'someValue3')
];