Trigger filter only on click - angularjs

I have a list of data, this data is filtered by a dropdown menu.
The problem is, i want the filtering to be triggered only on a button click, not on the dropdown change.
<select ng-model="annee" ng-options="annee.titre for annee in annees track by annee.id">
</select>
<input type="submit" name="submit" value="Filtrer">
<ul>
<li ng-repeat="x in accueils | filter:annee" >
{{x.titre}}
<div ng-bind-html="x.description | to_trusted"></div>
{{x.date}}
{{x.cout}} $
{{x.participants}} participants
</li>
</ul>
Here is a working example :
http://plnkr.co/edit/MbfrhdKfbTObybsQvxrR?p=preview
I want the filter to be triggered on clicking on the "filter" button
Is it possible ?
Thanks a lot!

Note that your filter code here doesn't match your Plunker; it's filter:{annee:annee.id} in the Plunker.
You want to decouple the ng-repeat from the ng-model. One way to do this is to filter based on a new property and update that property only when the Filter button is clicked.
In your HTML:
Add a <form> element and set ng-submit to call submit() when the Filter button is pressed:
<form ng-app="myApp" ng-controller="customersCtrl" ng-submit="submit()">
Change the ng-repeat filter to use a new property instead of the property used by the <select> element's ng-model:
<li ng-repeat="x in accueils | filter:{annee:currentAnnee.id}">
In your controller:
Create the new property initialized with an invalid id:
$scope.currentAnnee = {
"id": 0
};
Create a submit() function that sets the new property from the <select> element's ng-model:
$scope.submit = function() {
$scope.currentAnnee = $scope.annee;
};
See this Plunker for a complete example.

As pointed by #msmolens, there were some differences in your plunker and the code you posted here. Secondly, the two arrays that you have used, have nothing in common so for demonstration purposes i have changed the structure of the second array that will be used as filter.
To start with, decouple your Array filter from the model value of the select drop down.
<select ng-model="annee" ng-options="annee.date for annee in annees track by annee.id">
</select>
<input type="submit" name="submit" value="Filtrer" ng-click="filter()">
<ul>
<li ng-repeat="x in accueils | filter:filterExpr" >
{{x.titre}}
<div ng-bind-html="x.description | to_trusted"></div>
{{x.date}}
{{x.cout}} $
{{x.participants}} participants
</li>
</ul>
As visible in the code, we have a model variable for the filter expression in the ng-repeat.
We then initialize the filter expression with a blank value.
$scope.filterExpr = {"date" : ''};
There after, you just need to capture ng-click of the filter button and modify the variable being used as a filter.
$scope.filter = function() {
$scope.filterExpr = {"date" : $scope.annee.date};
};
You can find the updated plunker here.

Related

using group by and showing-hiding the group div for selected checkbox

I need to be able to group check boxes based on their categories and show only the group from which items have been selected and hide others.
But as per my code , it shows and hides but checks all check boxes of selected category.ow do I modify it to fix this issue?
I understand it is because of what i am returning but h
Here is what I have:
HTML:
<div ng-controller="dataController">
<div>
<!--<ul ng-repeat="(key, value) in properties | groupBy: 'name'" ng-show='(properties | filter: filterByCategory)'">-->
<ul ng-repeat="(key,value) in filtered=(properties | filter:filterByCategory| groupBy: 'name') ">
<li>Group name: <strong>{{ key }}</strong></li>
<div ng-repeat="prop in value">
<label>
<input type="checkbox" ng-model="filter[key]"/>
<span>{{prop.Property}}</span>
</label>
</div>
</ul>
JS:
$scope.filter = {};
$scope.filterByCategory = function (prop) {
return $scope.filter[prop.name] || noFilter($scope.filter);
};
function noFilter(filterObj) {
for (var key in filterObj) {
if (filterObj[key]) {
return false;
}
}
return true;
}
You ng-repeat your checkboxes over prop in value, but use the grouped key for the checkbox ng-model.
This means all your checkboxes of a group share the same ng-model expression and thus the same scope property - checking one will of course check all the others.
I can't really tell what you are trying to achieve with your filter object, but you will need to use separate ng-model expressions for your checkboxes to let them have separate states.

Assigning ng-model to checkboxes generated by ng-repeat

I have set up a json containing a list of countries with an ID and Country code attached:
It looks like this:
$scope.countries = [
{"name":"Afghanistan","id":"AFG","country-code":"004"},
{"name":"Ă…land Islands","id":"ALA","country-code":"248"},
{"name":"Albania","id":"ALB","country-code":"008"},
{"name":"Algeria","id":"DZA","country-code":"012"}
]
I then use the ng-repeat directive to create checkbox inputs for every country.
<div ng-repeat="country in countries">
<label><input type="checkbox" ng-model="{{country.id}}" ng-true-value="'{{country.name}}'" ng-false-value="''">{{country.name}}</label>
</div>
However when I run the code I only get the following to display:
Location
checkbox here {{country.name}}
If I remove the ng-model part of the repeat my checkboxes generate fine but I need a unique ng-model to be attached to every checkbox
ng-model="{{country.id}}"
How would I go about attaching a unique ng-model value?
This answer (Generate ng-model inside ng-repeat) does not provide a unique ng-model value
I will suggest you, use:
<div ng-repeat="country in countries">
<label><input type="checkbox" ng-model="myCountry.selected[country.id]" ng-true-value="'{{country.name}}'" ng-false-value="''">{{country.name}}</label>
</div>
{{myCountry.selected}}
JS:
$scope.myCountry = {
selected:{}
};

ngRepeat orderBy update after ngModel is updated

I have a list of text fields with a button below it. I can add text fields to that list dynamically with AngularJS.
The text field by default has an empty value. But I want to order the position of the list item as soon as I update the value of that text field. But when I do that the orderBy isn't triggered.
How can I make this happen?
Here's a quick demo: http://jsfiddle.net/fqnKt/214/
I just wanted to specifically note why the example was wrong (because I had the same issue even though I was using the orderBy directive).
DO NOT USE
track by $index
In your ng-repeat
I think that this is what you want:
<div ng-app="myApp">
<div ng-controller="MyCtrl">
<ul>
<li ng-repeat="item in items | orderBy:'name'">
<input type="text" ng-model="item.name" /> {{item.name}}
</li>
</ul>
<input ng-model="newItem" type="text"></input>
<button ng-click="add(newItem)">Add</button>
</div>
</div>
Working Example

Show HTML element if the Array provided has a nested Array using Angular.js

I want to populate a dropdown with an array, and if the user chooses an option that has a nested array, Then and only then I want to show another dropdown and populate it with that child array, and so on.
And then populate a hidden field with the last value of the chain.
How would I approach this with Angular.js?
You can use ng-show to conditionally show/hide the second drop-down
The code can be seen/tested here
Controller:
app.controller('MainCtrl', function($scope) {
$scope.items = [
{name:'item1'},
{name:'item2', subItems: [
{name:'sub item 1'},
{name:'sub item 2'}]}];
});
Markup:
<p>
<select ng-model="selectedItem" ng-options="i.name for i in items"></select>
</p>
<p ng-show="selectedItem.subItems">
<select ng-model="selectedSubItem" ng-options="i.name for i in selectedItem.subItems"></select>
</p>
Use ng-change directive in your select tag and in ng-change call a function that checks your scenario.
If you provide your array data, the answer can be given more accurately.
I know this approach is a long run. But it helps you to keep your code clean.
MARKUP
<select ng-model="selectedItem" ng-options="item.name for item in items" ng-change="doesItemHaveSubArray(selectedItem)"></select>
<div ng-if="subItem">
<select ng-model="selectedSubItem" ng-options="item.name for item in subItem"></select>
</div>
In JS
$scope.doesItemHaveSubArray=function(item){
if(item!==undefined){
$scope.subItem=item.subItems;
}
}

Reference the inputs created with ng-repeat in angular based on the number of variable options

The problem I'm facing, as outlined in the code, is that I can't seem to find out how to bind the second checkboxes (created with ng-repeat) to some model which I would then be able to use further down the code (showing/hiding yet another set of options). Also, I managed to show the additional number of inputs based on the count parameter in the $scope.availableOptions by using the $scope.getItterator function, but now I don't see how would I access the values of these checkboxes? I know I have to somehow use the option "ng-model" but am failing to do so, so any help appreciated.
My code is here, but am showing it here too:
html:
<div ng-controller='MyCtrl'>
Show additional options <input type="checkbox" ng-model="additionalOptions">
<div ng-show="additionalOptions">
<ul>
<li ng-repeat="option in availableOptions">
<label class="checkbox" for="opt_{{option.id}}">
<input type="checkbox" name="opt_{{option.id}}" id="opt_{{option.}}" />
{{option.name}}
<ul ng-show="if the upper checkbox is clicked">
<li>
<input type="text" ng-repeat="i in getItterator(option.count)" ng-model="SOME_VALUE_TO_BE_USED_BELOW"/>
Output the value based on what's entered above in the textboxes (SOME_VALUE_TO_BE_USED_BELOW)
</li>
</ul>
</label>
</li>
</ul>
</div>
</div>
and my js:
function MyCtrl($scope) {
$scope.availableOptions = [{"id":"1","name":"easy","count":"2"},{"id":"2","name":"medium","count":"3"},{"id":"3","name":"hard","count":"2"}];
$scope.getItterator=function(n){
var a = new Array();
for(var i=1; i <= n; i++)
a.push(i);
return a;
};
}
Try ng-model="option.checked":
<input type="checkbox" name="opt_{{option.id}}" id="opt_{{option.}}" ng-model="option.checked"/>
And then you can access this property further below like this:
<ul ng-show="option.checked">
DEMO
If you need to also reference the text box inputs. You create a new property (values) on the option. Like this:
{"id":"1","name":"easy","count":"2",values:[]}
Html:
<div ng-repeat="i in getItterator(option.count)">
<input type="text" ng-model="option.values[$index]"/>
{{option.values[$index]}}
</div>
DEMO
Use this:
<input type="checkbox" name="opt_{{option.id}}" id="opt_{{option.}}" ng-model="option.clicked"/>
{{option.name}}
<ul ng-show="option.clicked">
Basically, you are saying that the top checkbox should store its value in a model for each option option.clicked. And then only showing the information based on the scope item.
Updated Fiddle:
http://jsfiddle.net/CkHhJ/26/
UPDATE:
Here is another updated fiddle to answer your questions second part: http://jsfiddle.net/CkHhJ/27/
The difficulties you were having is likely because you are trying to build dynamic input models. Just bear in mind that you need to use an object for the dynamic values (not a plain string, eg: option.answers[$index].value and not just option.answers[$index]. See: AngularJS: Updating an input with a dynamic ng-model blurs on each key press

Resources