Let's say I have a 4 div tags in my view:
<div class="tile"></div>
<div class="tile"></div>
<div class="tile"></div>
<div class="tile"></div>
And let's say that when the user selects clicks on one of them I want the rest to, say, turn red. Normally in a dirty jQuery style I'd use something like:
var tiles = $('.tile');
tiles.click(function()
{
tiles.css('background', 'red');
});
However, how would I do this in the world of AngularJS? Would I stick this code in the controller and have it relative to the $scope? Or would I create a directive and bind that to each tile element?
Assuming that you wouldn't just have 4 random tiles in your interface not bound to some kind of model, you could do something like this:
http://jsfiddle.net/V4YC9/1/
HTML
<div ng-app ng-controller="x">
<div ng-repeat="tile in tiles" ng-click="selectTile(tile)" ng-class="tile.class">{{tile.name}}</div>
</div>
JavaScript
function x($scope) {
$scope.selectedTileIndex = null;
$scope.tiles = [
{id: 1, name: 'tile 1'},
{id: 2, name: 'tile 2'},
{id: 3, name: 'tile 3'},
{id: 4, name: 'tile 4'}
];
// provide default class to all tiles
angular.forEach($scope.tiles, function (tile) {
tile.class = 'tile';
});
$scope.selectTile = function (clickedTile) {
angular.forEach($scope.tiles, function (tile) {
tile.class = 'tileNotSelected';
});
clickedTile.class = 'tileSelected';
}
}
Edit: There are probably 10 different ways to do it. If you don't want to muddy up your model, you could store a separate array in $scope and calculate the class real time by saying ng-class="calculateTileClass(tile)", similar to what I did in my initial response: http://jsfiddle.net/V4YC9/1/
Related
Can someone help on how to re-write the below code in Angular. I am having problem in handling filters
ng-repeat="data in myController.data | filter:{filterFlag:'true'}"
AngularJS
Lets say you have an array of objects (in your case named data) in your myController i.e.
this.data = [
{id: 1, name: 'Oscar', age: 36},
{id: 2, name: 'Nina', age: 36},
{id: 3, name: 'Alex', age: 39},
]
And you want to filter out people with the age 36, you could iterate over it in the template like this:
<div ng-repeat="data in myController.data | filter:{age:36}">
{{data}}
</div>
Angular
In any case, filters are expensive. Thats why they are considered bad practice, thats why you are not recommended to use it in Angular. The style guide says, you ought to filter out the objects in the controller, rather than in the template. You might want to consider doing the same in AngularJS. You could write a method which does the job.
For more go to ... ng-repeat :filter by single field
I have searched for a solution to my problem but have not been able to find the right answer.
I have a list of all questions and a list of selected questions. I need to build a list of checkboxes from the list of all questions and check the ones that are in the list of selected questions. When changes are made to the checkboxes, I need the list of selected questions to be updated accordingly. The list of all questions never changes. How can I accomplish this? Here's a very abbreviated version of my situation:
var MyApp = angular.module('MyApp', []);
MyApp.controller('MyController', ['$scope', function ($scope) {
$scope.allQuestions = [
{ q_id: 1, q_txt: 'What time is it?', q_sort: 1},
{ q_id: 2, q_txt: 'What is that?', q_sort: 2},
{ q_id: 3, q_txt: 'Who are you?', q_sort: 4},
{ q_id: 4, q_txt: 'What color is that?', q_sort: 3}
];
$scope.selectedQuestions = [
{ q_id: 1, other_prop: 'yyy' },
{ q_id: 4, other_prop: 'zzz' },
];
}]);
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="MyApp" ng-controller="MyController">
<div ng-repeat="question in allQuestions"><input type="checkbox" ng-model="x" /> {{ question.q_txt }}</div>
</div>
In my application the lists come from a server and I would like to be able to return the selected questions list as an object back to the server when saving the changes.
I can't figure out the binding to accomplish this, or how to check the right checkboxes. Notice that the two lists are different, but bothe have the q_id value as the key to match them. Any help would be greatly appreciated.
It doesn't sound like you need to worry about which questions are selected until the user submits the form, so I'd just loop through the list of all questions at that time and create an array of the selected questions.
Something like this:
function getSelections() {
var selectedQuestions = []
$scope.allQuestions.forEach( function(question) {
if (question.selected) {
var questionCopy = angular.copy(question)
selectedQuestions.push(questionCopy)
}
})
return selectedQuestions
}
Then call this function before you post and pass the results to your API.
You should just be able to use ng-model to handle preselecting the checkboxes that should be preselected with:
<div ng-repeat="question in allQuestions"><input type="checkbox" ng-model="question.selected" /> {{ question.q_txt }}</div>
Something like this should do the trick. Using array.find() might be more efficient. Using a library like _ would make this easier.
$scope.selectedQuestions.map( function(selectedQuestion) {
var match = $scope.allQuestions.some( function(question) {
if (question.q_id == selectedQuestion.q_id) {
question.selected = true
return true
}
return false
}
}
What I'm trying to do is have a service (lets say: myService) that holds specific data like objects representing printers present and selected:
var localPrinters = [{ id: 12, name: 'HP', type: 'laser' },
{ id: 33, name: 'Lexmark', type: 'laser' }];
var activePrinter = {};
In some view that gets shown occasionally (like app settings), I have a controller that would define variables in the local scope which would point to the objects in the injected myService.
The view would then use ng-repeat to iterate over printer objects in localPrinters and display radio buttons that correspond to each object in the array..
Now i need two things..
1) update the activePrinter upon radiobutton selection change with the corresponding object value
2) in case the activePrinter already contains an object, when the view loads i want the corresponding radio to be checked already (if its value object matches the object in activePrinter, otherwise none should be selected.
I've managed 1) in a couple of ways.. either sticking to the model usage or adding methods to call upon ng-change.
//pseudocode
<container ng-repeat="printer in printers" >
<radio ng-value="printer" ng-model="$scope.activePrinter"/>
</container>
or
//pseudocode
<container ng-repeat="printer in printers" >
<radio ng-value="printer" ng-change="selectPrinter(printer)" "ng-model="$scope.activePrinter"/>
</container>
What i'm having trouble with is 2)
Not sure if there's a way in angular to automatically figure out some of the printer values matches the activePrinter selection and make the radio checked. Also not sure of the way i'm using ng-model for this purpose.
Any pointers?
Thanks!
You can do that in this way:
var app = angular.module('app', []);
app.controller('firstCtrl', function($scope) {
$scope.printers = [{
id: 12,
name: 'HP',
type: 'laser'
}, {
id: 33,
name: 'Lexmark',
type: 'laser'
}];
$scope.activePrinter = {};
//set default printer
$scope.activePrinter.printer = $scope.printers[0]
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<body ng-app="app">
<div ng-controller="firstCtrl">
<div class="container" ng-repeat="printer in printers">
<label>{{printer.name}}</label>
<input type="radio" ng-value="printer" ng-model="activePrinter.printer" />
</div>
Active Printer:{{activePrinter.printer.id}} | {{activePrinter.printer.name}} | {{activePrinter.printer.type}}
</div>
</body>
I've got an angularjs application that has a form/controller that look essentially like this (boiled down to the pertinent stuff):
angular.module('testApp', [])
.controller('testCtrl', function ($scope) {
$scope.envelopes = [{
id: 1,
name: 'first',
default_spend: '1'
}, {
id: 2,
name: 'second',
default_spend: '0'
}, {
id: 3,
name: 'third',
default_spend: '0'
}, ];
});
And a form that looks roughly like this:
<div ng-app="testApp">
<div ng-controller="testCtrl">
<div ng-repeat="envelope in envelopes">
<div>{{envelope.name}}
<input type="radio" name="default_spend" ng-model="envelope.default_spend" ng-value="1" />
Default Spend: {{envelope.default_spend}}
</div>
</div>
</div>
</div>
You can see this in action with this fiddle.
As you can see, the first envelope is marked as the default_spend envelope and the other two aren't. When I select a different envelope, that envelope also gets marked as the default_spend, but when the radio button is unselected, the model value stays the same ("1"). I understand that I'm dealing with a child scope here due to ng-repeat, but is there a way for me to set an "unselected" value without having to jump through hoops with ngChange?
Not really. When you use ng-value it is what is going to get bound to the ng-model and in your case all of them are having value 1. Also i really did not get the purpose of toggling 1 and 0, however you could just achieve it this way:-
<input type="radio" name="default_spend"
ng-click="selected.envelope = envelope" /> <!--Register an ng-click and set selected one
Default Spend: {{getDefSpend(envelope)}}</div> <!-- Show the text based on selection-->
And in your controller:-
$scope.selected = {envelope: $scope.envelopes[0]};
$scope.getDefSpend = function(envelope){
return $scope.selected.envelope === envelope ? 1 : 0;
}
//$scope.selected.envelope will be your selected option at any point.
Demo
It's because what you have is actually 3 different model values. To work as you want it, you would have ONE model value for all 3. You can either restructure your data, or use ng-change to modify your model manually.
I am trying to use this plugin in my project to have multiple range slider within ng-repeat. http://prajwalkman.github.io/angular-slider/
The plugin works fine when there is single slider , but when i try to put multiple slider in ng-repeat it doesn't work.
Not sure is there anything wrong with my codes or the plugin doesn't support that.
Is there anyway i can make it work?
Here is the demo plnkr.
http://plnkr.co/edit/9H7WF44X7zCWaw91jDyr?p=preview
<body ng-controller='PriceCtrl'>
{{position}}
<div>
<slider floor="10" ceiling="60" ng-model-low="position.minAge" ng-model-high="position.maxAge"></slider>
</div>
<div ng-repeat="item in items">
{{item}}
<slider floor="10" ceiling="60" ng-model-low="item.minPrice" ng-model-high="item.maxPrice"></slider>
</div>
</body>
app.controller('PriceCtrl', function ($scope){
$scope.items = [{name: "item 1", minPrice: 10,
maxPrice: 50},
{name: "item 2", minPrice: 5,
maxPrice: 40},
{name: "item 3", minPrice: 15,
maxPrice: 30}];
$scope.lower_price_bound = 0;
$scope.upper_price_bound = 50;
$scope.position = {
name: 'Potato Master',
minAge: 25,
maxAge: 40
};
});
You can use rg-slider
It's allows you to use multiple sliders in one page.