AngularJS - Update selected options for multiple select - angularjs

I'd like to make a simple "autocomplete". Enter keyword into input and select the result. Then the selected items will be shown. I'm currently stucking in how to change the hidden select and show selected items. Could you help me?
<div ng-controller="MyCtrl">
<input type="search" ng-model="query">
<ul ng-repeat="game in games | filter:query" ng-show="query.length >= 2 && (games | filter:query).length">
<li><a ng-click="selectGame(game.id)">{{ game.name }}</a></li>
</ul>
<select multiple name="games" style="display:none;" ng-options="game.id as game.name for game in games"></select>
<ul class="selected-games">
<li>{{ game.name }} - {{ game.year }}</li>
</ul>
</div>
<script type="text/javascript">
function MyCtrl($scope, $http) {
$http.get('/ajax/all/games/').success(function(data){
$scope.games = data;
});
$scope.selectGame = function() {}; //?
}
//MyCtrl.$inject = ['$scope', '$http'];
// JSON data from URL
var games = [
{'id': 1, 'name': 'Halo', 'year': '2005'},
{'id': 2, 'name': 'Final Fantasy', 'year': '2008'},
{'id': 3, 'name': 'Guitar Heroes', 'year': '2008'},
{'id': 4, 'name': 'Warcraft', 'year': '2003'},
{'id': 5, 'name': 'Starcraft II', 'year': '2010'},
{'id': 6, 'name': 'Fifa 12', 'year': '2012'},
];
</script>

Its hard to understand what your desired result is, but check out my updates here: http://jsfiddle.net/rS6Hz/1/. I added a new variable to the scope, an array called selectedGames and implemented the ng-click by adding to that array.
$scope.selectedGames = [];
$scope.selectGame = function(game) {
$scope.selectedGames.push(game);
};
Then, in the display, you have to add an ng-model to the select for it to do anything (as far as I can tell) and the ul of selected-games needs an ng-repeater to loop over the selectedGames
<select multiple name="games" ng-model="something" ng-options="game.id as game.name for game in selectedGames"></select>
<h1>Selected Games</h1>
<ul class="selected-games">
<li ng-repeat="game in selectedGames">{{ game.name }} - {{ game.year }}</li>
</ul>
(I removed the display: none; on the select in order to see it.

Here is another way, without using a separate variable:
http://jsfiddle.net/9Ag9r/
Basically:
<ul class="selected-games">
<li ng-repeat='game in games | filter:{selected:true}'>{{ game.name }} - {{ game.year }}</li>
</ul>
I believe it is a cleaner solution than the accepted one

Related

ng-repeat array in array filtering by property of parent with AngularJS

I want to select an array in array by property of the parent. I don't know the index (in this case 1), but I know the id. Can I do it? This is my working example with index, I want same results by id (43).
<script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.4.8/angular.min.js"></script>
<div data-ng-app="myApp" data-ng-controller="myCtrl">
<ul>
<li ng-repeat="p in people[1].rooms" ng-bind="p"></li>
</ul>
</div>
<script>
var app = angular.module('myApp', []);
app.controller('myCtrl', function($scope) {
$scope.people = [
{
id: 25,
nick: 'Joker',
rooms: ['room1', 'room2']
},
{
id: 43,
nick: 'King',
rooms: ['room3', 'room4']
},
{
id: 78,
nick: 'Queen',
rooms: ['room5', 'room6']
}
]
});
</script>
You should separate get rooms for particular user by its id using strict filter on people array. Its obvious that you are going to a single record as its id based search.
Code
<ul>
<li ng-repeat="p in filteredPeople = (people | filter: {id: l.id })[0].rooms">
{{p}}
</li>
</ul>
This is one option:
<ul ng-repeat="p in people | filter: { id: 45 }">
<li ng-repeat="room in p.rooms" ng-bind="room"></li>
</ul>

Conditional ngRepeat based on dropdown

I would like to display a list based on which item is selected in a dropdown.
When I use the code below, I'm getting this error:
TypeError: Cannot read property 'type' of undefined
Any suggestions on how to do this right?
HTML:
<select class="form-control" ng-model="editProject.project.type"
ng-options="project as project.type for project in editProject.options track by project.type">
</select>
<ul class="list-group">
<li class="list-group-item" ng-repeat="benefit in editProject.foods()">{{snack}}</li>
</ul>
Controller:
.controller('EditProjectCtrl', function () {
var editProject = this;
editProject.options = [
{'type': 'Fruits'},
{'type': 'Vegetables'},
{'type': 'Desserts'}
];
editProject.snacks = function() {
if(editProject.project.type == 'Fruits') {return [
'Grapes',
'Oranges',
'Apples',
]}
if(editProject.project.type == 'Vegetables') {return [
'Broccoli',
'Spinache',
'Kale',
]}
else {return [
'Cookies',
'Cake',
'Pie']}
};
You are almost there. There was a mismatch between the ng-model of the select element, and the conditions in the controller. I also replaced benefit in editProject.foods() with snack in editProject.snacks():
<select class="form-control" ng-model="editProject.project" ng-options="project as project.type for project in editProject.options track by project.type"></select>
<ul class="list-group">
<li class="list-group-item" ng-repeat="snack in editProject.snacks()">{{snack}}</li>
</ul>
Because editProject.project is not defined until you select a project, you have to initialize it in the controller:
editProject.project = {};
See fiddle

AngularJS search page in table contents

Hi I'm new to this framework and I have to change some webapp.
There is already something like this:
<input type="text" class="catalog-search input input--large input--full" ng-model="search">
and
<ul class="catalog-list catalog-scroll">
<li ng-repeat="rodzic in list | groupBy:'styl' | toArray:true | orderBy:!'$key'">
{{rodzic.$key}}
<ul>
<li ng-repeat="dziecko in rodzic | filter:search | bookmark:search" ng-class="{active:isActiveTab(dziecko)}" ng-click="openItem(dziecko)">
{{dziecko.rodzina}}
<b>{{dziecko.page}}</b>
</li>
</ul>
</li>
</ul>
The above code create table of contents for pdf file.When I type some word in input field searching works fine but I can't search by number,let's say I want to find page number 3.
What should I change to be able to find by page number?
Thx in advance.
I see no such problem of searching by numbers. I put a simplified version of your code into Plnkr and I can search by words or numbers - even if the numbers are sometimes numeric values and sometimes strings.
Search on 6 or 7 (which are numeric values) or 3 (which is a string '333'). Both work.
Can you modify my Plunk to show the problem?
Here's my HTML:
<body ng-controller="MainCtrl">
<input type="text" class="catalog-search input input--large input--full" ng-model="search">
<ul class="catalog-list catalog-scroll">
<li ng-repeat="rodzic in list">
{{rodzic.$key}}
<ul>
<li ng-repeat="dziecko in rodzic | filter:search" ng-class="{active:isActiveTab(dziecko)}" ng-click="openItem(dziecko)">
{{dziecko.rodzina}}
<b>{{dziecko.page}}</b>
</li>
</ul>
</li>
</ul>
</body>
Here's my controller with some mock data which I think simulates yours well enough for this demonstration.
var app = angular.module('plunker', []);
app.controller('MainCtrl', function($scope) {
$scope.name = 'World';
$scope.list = [
[{
rodzina: 'This is one',
page: '111'
}, {
rodzina: 'This is two',
page: '222'
}, {
rodzina: 'This is three',
page: '333'
}],
[{
rodzina: 'This is four',
page: '444'
}, {
rodzina: 'This is five',
page: '555'
}, {
rodzina: 'This is six',
page: 666
}],
[{
rodzina: 'This is seven',
page: 777
}, {
rodzina: 'This is eight',
page: '888'
}, {
rodzina: 'This is nine',
page: '999'
}],
]
});

Data-binding is not updating ng-repeat section

I'm new to angularjs and I have a data binding issue.
After each repeated line, I want to show a number of mutually exclusive options. These would be images using a background-image, and when the option is selected I add the css class 'selected' to the span containing the image.
I've simplified it below to show options A, B and C and to make the currently selected one bold. By clicking on A, B or C you change the option.
The inner ng-repeat section is not evaluated again (it seems) when the model changes, but as the "Debugging category" shows, the outer ng-repeat is re-evaluated and the "Debugging category" shows correctly that the category has been changed.
I'm clearly missing something about angularjs; how can I get the inner ng-repeat to re-evaluate to that the correct style is applied to the A, B and C options?
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<script>
var testApp = angular.module('testApp', []);
testApp.controller('NamesCtrl', function ($scope) {
$scope.categories = [ 'A', 'B', 'C' ];
$scope.names = [
{ name: 'John', category: 'C' },
{ name: 'Cindy', category: 'A' },
{ name: 'Patrick', category: 'B' }
];
$scope.changeCategory = function(name, category) {
name.category = category;
};
});
</script>
<body ng-app="testApp">
<h1>Names</h1>
<div ng-controller="NamesCtrl">
<ul>
<li ng-repeat="name in names">
<span>{{name.name}}</span>
<span ng-repeat="category in categories" ng-init="selected = (category == name.category)">
<span ng-style="{'true': {'font-weight': 'bold'}, false: {}}[selected]" ng-click="changeCategory(name, category)">{{category}}</span>
</span>
<em>(Debugging category: {{name.category}})</em>
</li>
</ul>
</div>
</body>
ng-init expression is not watched and updated automatically whenever related scope property value changes, you could just solve this by removing ng-init and using the expression directly
<span ng-style="{'true': {'font-weight': 'bold'}}[category == name.category]"
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<script>
var testApp = angular.module('testApp', []);
testApp.controller('NamesCtrl', function ($scope) {
$scope.categories = [ 'A', 'B', 'C' ];
$scope.names = [
{ name: 'John', category: 'C' },
{ name: 'Cindy', category: 'A' },
{ name: 'Patrick', category: 'B' }
];
$scope.changeCategory = function(name, category) {
name.category = category;
};
});
</script>
<body ng-app="testApp">
<h1>Names</h1>
<div ng-controller="NamesCtrl">
<ul>
<li ng-repeat="name in names">
<span>{{name.name}}</span>
<span ng-repeat="category in categories" >
<span ng-style="{'true': {'font-weight': 'bold'}}[category == name.category]" ng-click="changeCategory(name, category)">{{category}}</span>
</span>
<em>(Debugging category: {{name.category}})</em>
</li>
</ul>
</div>
</body>

Creating a dynanic form in AngularJS with nested lists

I have a model in AngularJS that is structured like so:
region = { 'substances': [
{ 'id': 123, 'name': 'Hello', 'versions': ['A', 'B', 'C'] },
{ 'id': 456, 'name': 'World', 'versions': ['A', 'B', 'C'] }
]}
I want to be able to display and modify this model in a form. Currently I have nested ng-repeats:
<ul>
<li ng-repeat="substance in region.substances">
<input name="substance[]" class="input-medium" type="text" ng-model="substance.name">
<ul>
<li ng-repeat="version in substance.versions">
<input style="margin-left: 10px;" type="text" name="<% substance.id %>.version[]" class="input-medium" ng-model="version">
</li>
</ul>
</li>
</ul>
(Note: I've redefined AngularJS brackets to be <% %>).
I can modify the name, but I AngularJS prevents me from even typing in the inner inputs. I'm guessing that I'm not binding to the model correctly? Also, how would I go about adding another "substance" that has a name and a list of versions?
Is there a proper way to be naming my inputs?
As suggested by #Yoshi , is always easiest to use object inheritance rather than primitive within nested scopes.
$scope.region = { substances: [
{ name: 'Hello', versions: [{x:'A'},{x: 'B'},{x: 'C'}] },
{ name: 'World', versions: [{x:'A'},{x: 'B'},{x: 'C'}] }
]};
<ul>
<li ng-repeat="substance in region.substances">
<input class="input-medium" type="text" ng-model="substance.name">
<ul>
<li ng-repeat="version in substance.versions">
<input type="text" ng-model="version.x">
</li>
</ul>
</li>
</ul>
Demo

Resources