My problem is when i change the value of the dropdown menu the value isn't displayed in the dropdown menu but the correct value is displayed in my console. Not sure why it isn't working at the moment because i have a same implementation of this in another project. Maybe i'm overlooking things.
On initialization i set
selected_type = types[0]
// What will result in Type1 being displayed on page load.
Fiddle you can find here: https://jsfiddle.net/596tzsh8/7/
Use:
ng-options="selected_type as selected_type.Name for selected_type in types track by selected_type.Id"
// ^
// the object itself
... instead of:
ng-options="selected_type.Id as selected_type.Name for selected_type in types track by selected_type.Id"
// ^
// the object's ID
Then, in your callback function, replace:
var typeID = this.selected_type;
// ^
// the object itself
... by:
var typeID = this.selected_type.Id;
// ^
// the object's ID
... and you're all set!
See your forked JSFiddle here, or play around with the snippet below.
var app = angular.module("app", ["controllers"])
var controllers = angular.module("controllers",[]);
controllers.controller('myController', function($scope){
$scope.types = [{
Id: 1,
Name: 'Type1'
}, {
Id: 2,
Name: 'Type2'
}, {
Id: 3,
Name: 'Type3'
}];
$scope.GetValueTypeDropdown = function () {
var typeID = this.selected_type.Id;
$scope.the_type = $.grep($scope.types, function (selected_type){
return selected_type.Id == typeID;
})[0].Name;
console.log($scope.the_type);
return $scope.the_type;
};
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="app">
<div ng-controller="myController">
<form>
<select name="type" class="col-xs-12 dropdown-list"
ng-model="selected_type" class="col-xs-8"
ng-init="selected_type = types[0]"
ng-options="selected_type as selected_type.Name for selected_type in types track by selected_type.Id"
ng-change="GetValueTypeDropdown()">
</select>
</form>
</div>
</div>
You can change the select as follows,
<select name="type" class="col-xs-12 dropdown-list" ng-model="selected_type" class="col-xs-8" ng-init="selected_type = types[0]" ng-options="type as type.Name for type in types track by type.Id" ng-change="GetValueTypeDropdown()">
also you can have a $scope variable and display it on ng-change
$scope.GetValueTypeDropdown = function() {
console.log($scope.selected);
};
DEMO
Related
I am trying to add my $scope together, but having issues with it.
I am using
$scope.total = ($scope.list_category1.id || 0) + ($scope.list_category2.id || 0) + ($scope.list_category3.id || 0);
but I can't seem to add my values together until all the selects have got a value.
Please help
https://jsfiddle.net/wayneker/o9t6g7qg/8
If you watch console closely, every time calcTotals() is executed, you get error Cannot read property 'id' of undefined as list_category1 expected to be an Object and id property is not found within it. You should create default values like zeros to make sure calcTotals() will successfully function:
Object.assign($scope, {
list_category1: '',
list_category2: '',
list_category3: ''
});
Empty string are only for example as they are most easiest way to define default values for your... err... view model.
You can directly call the calcTotals instead of total.
and change the function as,
$scope.calcTotals = function(){
return ($scope.list_category1.id || 0) + ($scope.list_category2.id || 0) + ($scope.list_category3.id || 0);
};
DEMO
var app = angular.module('app', []);
app.controller('Ctrl',function($scope) {
$scope.list_categories = {
data: [
{id: 1, name: 'name1'},
{id: 2, name: 'name2'},
{id: 3, name: 'name3'},
{id: 4, name: 'name4'}
]
};
$scope.total = 0;
$scope.calcTotals = function(){
return ($scope.list_category1.id || 0) + ($scope.list_category2.id || 0) + ($scope.list_category3.id || 0);
};
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="app" ng-controller="Ctrl">
<select id="sel" class="input-block-level" ng-model="list_category1" ng-options="value.name for value in list_categories.data">
<option value="">Other</option>
</select>{{list_category1.id}}<br>
<select id="sel" ng-model="list_category2" ng-options="value.name for value in list_categories.data">
<option value="">Other</option>
</select>{{list_category2.id}}<br>
<select id="sel" ng-model="list_category3" ng-options="value.name for value in list_categories.data">
<option value="">Other</option>
</select>{{list_category3.id}}<br>
<br>
<div>
<b>All Points (from $scope total): {{calcTotals()}}</b><br><br>
<b>All Points (by adding directly): {{list_category1.id + list_category2.id + list_category3.id}}</b>
</div>
</div>
I need to show object only if one of it's properties equals to array.
I have a controller in app.js:
app.controller('checkBoxController', function ($scope) {
$scope.ingredients= [
{label: 'Egg', value: 1},
{label: 'Milk', value: 2},
$scope.selection=[];
$scope.toggleSelection = function toggleSelection(ingredientLabel) {
var idx = $scope.selection.indexOf(ingredientLabel);
if (idx > -1) {
$scope.selection.splice(idx, 1);
}
else {
$scope.selection.push(ingredientLabel);
}
};
});
and an html code for it:
<span style="color:black;" class="selected-item">Selected Items:<span>
<div ng-repeat="label in selection" class="selected-item">
</div>
<div class="list-group">
<div class="list-group-item" ng-repeat="product in meals.products" ng-show="product.contents==selection">
<h1>{{product.name}}</h1>
<meal-gallery></meal-gallery>
<meal-tabs></meal-tabs>
</div>
</div>
And I Have { name: 'Scrambled Egg', contents: "Egg"} in array of products. So I need to show product if it's contents equals to selected ingredients.
I do not have problems when it is only one ingredient like "Egg", but if I need contents of two equal to selected?
It would be best to use a custom filter.
If you add lodash to your application, you can create a filter that will preform a following operation:
angular.module('common', [])
.filter('canBeMadeFrom', function() {
return function(product, ingredients) {
return _.intersection(product.contents, ingredients).length == product.contents.length';
};
});
this will return true if all of products contents are contained in ingredients
use it like this
ng-repeat='product in products | canBeMadeFrom:ingredients'
Use a filter.
<div ng-repeat=product in products |filter: product.a === a && product.b === b>
You can also use a function for filter. It's a function that takes in an item and returns Boolean
I'm trying to apply a check box filter to a list, but the options for the check boxes should also be come the list of items only,
it works fine if i am iterating it for all the check boxes,
the problem is coming when i am trying to apply the unique filter to display check boxes options.
i have included
angular 1.4 and ui-utils
<script src="js/angular.min.js"></script>
<script src="js/ui-utils.min.js"></script>
my view and controller are defined as:
<div ng-controller="Test">
<div ng-repeat="person in persons | unique:type">
<!-- record that this person has been selected -->
<input type="checkbox" ng-checked="person.checked" ng-model="person.checked" /> {{ person.type }}
</div>
<ul>
<li ng-repeat="person in persons | selectedTypes">{{person.name}}</li>
</ul>
</div>
and script is
<script>
var app = angular.module("MyApp", ['ui.utils']);
app.controller("Test", function($scope) {
$scope.persons = [
{ type: 1, name: 'Ankit Balyan' },
{ type: 1, name: 'Abhilaksh' },
{ type: 2, name: 'Sanket Srivastav' },
{ type: 2, name: 'Sachin Sharma' },
{ type: 2, name: 'Rohan Rathor' },
{ type: 2, name: 'Jim' },
];
$scope.$watch('persons', function() {
console.log($scope.persons);
})
});
// Define our filter
app.filter('selectedTypes', function($filter) {
return function(persons) {
var i, len;
// get persons that have been checked
var checkedPersons = $filter('filter')(persons, {checked: true});
// Add in a check to see if any persons were selected. If none, return
// them all without filters
if(checkedPersons.length == 0) {
return persons;
}
//console.log(checkedPersons);
// get all the unique cities that come from these checked persons
var types = {};
for(i = 0, len = checkedPersons.length; i < len; ++i) {
// if this checked persons cities isn't already in the cities object
// add it
if(!types.hasOwnProperty(checkedPersons[i].type)) {
types[checkedPersons[i].type] = true;
}
}
// Now that we have the cities that come from the checked persons, we can
//get all persons from those cities and return them
var ret = [];
for(i = 0, len = persons.length; i < len; ++i) {
// If this person's city exists in the cities object, add it to the
// return array
if(types[persons[i].type]) {
ret.push(persons[i]);
}
}
//console.log(persons.length);
// we have our result!
return ret;
};
});
</script>
You have to put the name of the property as a string :
<div ng-repeat="person in persons | unique: 'type'">
instead of
<div ng-repeat="person in persons | unique: type">
Edit: If you don't provide quotes, you are applying a unique filter by the value of the variable type, which is not defined in your case, therefore the filter has no effect.
I am facing a problem with my angular js bindings not being updated correctly.
I am trying to achieve a way to hide certain form elements and show others by clicking a "next" button.
I have setup some objects in my controller to hold values for input text fields and menu dropdowns, I also have setup a couple of button (next and previous and add) button to be able to add new objects and a next and previous buttons to be able to navigate between the different stored objects.
The problem that I am facing is that the input text field is being updated correctly when i press the next and previous button however the dropdown menus are not.
This is a link to a jsfiddle to help show the problem:
http://jsfiddle.net/bLs9yu3f/
Found two issues with the code in your Fiddle:
First, when assigning programOutcomes to the affects key of your objects (both when creating the initial one and pushing to add a new one) you where assigning programOutcomes directly, which assigns a pointer to the original array and doesn't create a copy. There are many ways to do this. I chose affects: JSON.parse(JSON.stringify(programOutcomes)). See the example below.
$scope.output.outcomes.push({
outcome: '',
affects: JSON.parse(JSON.stringify(programOutcomes))
});
Second, in the for loop of your addCourseOutcome function you refer to $scope.output.outcomes[0] instead of the latest $scope.output.outcomes you just pushed. The following code fixes this issue.
var lastest = $scope.output.outcomes.length - 1;
for (var i = 0; i < programOutcomes.length; i++) {
$scope.output.outcomes[lastest].affects[i].how = '';
}
This is a fork of your Fiddle with the corrections I mentioned above: http://jsfiddle.net/JohnnyEstilles/uz8zf2b0/.
angular.module('myapp', []).controller('ProgramsController', ['$scope',
function($scope) {
var programOutcomes = [{
outcome: 'po1'
}, {
outcome: 'po2'
}, {
outcome: 'po3'
}, {
outcome: 'po4'
}];
$scope.input = {
outcomeCounter: 0,
programOutcomes: programOutcomes,
actions: ['', 'I', 'E', 'R']
};
$scope.output = {
outcomes: [{
outcome: '',
affects: JSON.parse(JSON.stringify(programOutcomes))
}]
};
for (var i = 0; i < programOutcomes.length; i++) {
$scope.output.outcomes[0].affects[i].how = '';
}
$scope.nextOutcome = function() {
$scope.input.outcomeCounter++;
};
$scope.previousOutcome = function() {
$scope.input.outcomeCounter--;
};
$scope.deleteCourseOutcome = function() {
$scope.output.outcomes.splice($scope.input.outcomeCounter, 1);
$scope.input.outcomeCounter--;
};
$scope.addCourseOutcome = function() {
$scope.output.outcomes.push({
outcome: '',
affects: JSON.parse(JSON.stringify(programOutcomes))
});
/**
* create a 'how' property in the affects array
* to be used for storage of I, E, R
*/
var lastest = $scope.output.outcomes.length - 1;
console.log($scope.output.outcomes[lastest].affects);
for (var i = 0; i < programOutcomes.length; i++) {
$scope.output.outcomes[lastest].affects[i].how = '';
}
/**
* increment the outcomeCounter
*/
$scope.input.outcomeCounter++;
};
}
]);
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<body ng-app="myapp">
<div ng-controller="ProgramsController">
<div class="form-group">
<label for="outcome">Outcome</label>
<input id="outcome" placeholder="Outcome" class="form-control" ng-model="output.outcomes[input.outcomeCounter].outcome">
</div>
<div class="form-group">
<table class="table table-striped">
<tr ng-repeat="programOutcome in input.programOutcomes">
<td>{{programOutcome.outcome}}</td>
<td>
<select ng-model="output.outcomes[input.outcomeCounter].affects[$index].how" ng-options="value for value in input.actions">
</select>
</td>
</tr>
</table>
</div>
<div class="form-group">
<button class="btn" ng-click="addCourseOutcome()">Add outcome</button>
<button class="btn" ng-click="nextOutcome()"
ng-if="output.outcomes.length>1 && input.outcomeCounter !== (output.outcomes.length - 1)">
Next
</button>
<button class="btn" ng-click="previousOutcome()"
ng-if="output.outcomes.length>1 && input.outcomeCounter > 0">
Previous
</button>
<button class="btn btn-warning" ng-click="deleteCourseOutcome()">Delete outcome</button>
</div>
</div>
</body>
I have a AngularJS directive that allows users to select a values from a list to filter on. Pretty simple concept which is represented here:
Problem is when I click one of the checkboxes they all select unintended. My directive is pretty simple so I'm not sure why this is happening. The code around the selection and checkboxes is as follows:
$scope.tempFilter = {
id: ObjectId(),
fieldId: $scope.available[0].id,
filterType: 'contains'
};
$scope.toggleCheck = function (id) {
var values = $scope.tempFilter.value;
if (!values || !values.length) {
values = $scope.tempFilter.value = [];
}
var idx = values.indexOf(id);
if (idx === -1) {
values.push(id);
} else {
values.splice(idx, 1);
}
};
$scope.valuesListValues = function (id) {
return $scope.available.find(function (f) {
return f.id === id;
}).values;
};
and the data resembles:
$scope.available = [{
id: 23,
name: 'Store'
values: [
{ id: 124, name: "Kansas" },
{ id: 122, name: "Florida" }, ... ]
}, ... ]
the view logic is as follows:
<ul class="list-box">
<li ng-repeat="val in valuesListValues(tempFilter.fieldId)">
<div class="checkbox">
<label ng-click="toggleCheck(val.id)">
<input ng-checked="tempFilter.value.indexOf(val.id) === -1"
type="checkbox"> {{val.name}}
</label>
</div>
</li>
</ul>
First off, it toggleCheck fires twice but populates the correct data ( second time given my code it removes it though ).
After the second fire, it checks all boxes... Any ideas?
Perhaps its that the local variable doesn't get reassigned to the property of the scope property used in the view. Since your values are then non-existent and not found, the box is checked.
$scope.tempFilter.value = values
I took the interface concept you were after and created a simpler solution. It uses a checked property, found in each item of available[0].values, as the checkbox model. At the top of the list is a button that clears the selected items.
JavaScript:
function DataMock($scope) {
$scope.available = [{
id: 23,
name: 'Store',
values: [{
id: 124,
name: "Kansas"
}, {
id: 122,
name: "Florida"
}]
}];
$scope.clearSelection = function() {
var values = $scope.available[0].values;
for (var i = 0; i < values.length; i++) {
values[i].checked = false;
}
};
}
HTML:
<body ng-controller="DataMock">
<ul class="list-box">
<li>
<button ng-click="clearSelection()">Clear Selection</button>
</li>
<li ng-repeat="val in available[0].values">
<div class="checkbox">
<label>
<input ng-model="val.checked"
type="checkbox" /> {{val.name}}
</label>
</div>
</li>
</ul>
</body>
Demo on Plunker
The repeat that I used to grab the values based on the id, was the problem area.
<li ng-repeat="val in valuesListValues(tempFilter.fieldId)">
removing that and simple listening and setting a static variable resolved the problem.
$scope.$watch('tempFilter.fieldId', function () {
var fId = $scope.tempFilter.fieldId;
if ($scope.isFieldType(fId, 'valuesList')) {
$scope.valuesListValues = $scope.valuesListValues(fId);
}
}, true);
});
and then in the view:
ng-repeat="value in valuesListValues"