Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    text
    copied!<p>This is exactly what angular filters are for. I have written a <a href="http://jsfiddle.net/keqLK/2/" rel="nofollow">fiddle</a>, the explanation follows:</p> <pre><code>&lt;tr ng-repeat="app in applications | filter:myFilterFunction"&gt; &lt;td&gt;{{app.applicationId}}&lt;/td&gt; &lt;td&gt;{{app.projectName}}&lt;/td&gt; &lt;td&gt;{{app.createTime}}&lt;/td&gt; &lt;td&gt;{{app.status}}&lt;/td&gt; &lt;td&gt;{{app.createdByUserId}}&lt;/td&gt; &lt;/tr&gt; </code></pre> <p>The important part is the <code>myFilterFunction</code> which I have written on a controller but you can add it anywhere there is a scope.</p> <pre><code>var myapp = angular.module('myapp', []); myapp.controller('testController', ['$scope', function($scope) { $scope.myFilterFunction = function (item) { if (!$scope.hideSubmitted) return true; return item.status !== "submitted"; }; $scope.hideSubmitted = false; }]); </code></pre> <p>The <code>myFilterFunction</code> will be called for every element in the array and returns true for ones you'd like to have be visible. The checkbox now affects a value which alters the behavior of the filter without altering the actual model you are building your list from.</p> <p>Angular filters have the advantage of not changing the model you are building your view from, but ignoring the parts that you dont want to interact with right now. This is much less cumbersome than altering the model and storing the original state in another element. It's best to maintain one canonical model at all times and use angular filters to control what is actually shown.</p> <hr> <p>EDIT</p> <p>If you look at the above answer you will see I first create an angular module called <code>myapp</code> to build the app off of. Once you have the module, you have access to all of <a href="http://docs.angularjs.org/api/angular.Module" rel="nofollow">these functions</a> to build components with. One of which is <code>.filter</code> which I take it you know already because of your question in the comments.</p> <p>Finding the allowed syntax for all of these methods can be difficult, but the one I'll focus on is the one I like to refer to as the <em>only</em> one, and I have already given an example of it above. Any of the parameters to the functions on that take a function argument can actually be replaced by an array to use for <a href="http://docs.angularjs.org/guide/di" rel="nofollow">dependency injection</a>. If you search that page for <code>Inline Annotation</code> you will find the 3 formats that are allowed, and I will argue the only one you should be using is the last one, which takes the array I just talked about. So the signature of the filter looks like this:</p> <pre><code>myModule.filter('name', ['dependency1', 'dependency2', function(arg1, arg2) { }]); </code></pre> <p>The factory function must be the last argument and all of the dependencies map to the args in order regardless of name. You can have as many dependencies as you need. Even in the case that my service does not need any dependencies, I generally still use the array syntax to remind me to use it if I should need to add any dependencies.</p> <p>I prefer using this syntax because it keeps the dependencies close to the function, it keeps the service (filter in this case) as part of the module it belongs to and it's safe from js minifiers because the dependencies are referred to as strings.</p> <p>As for injecting scope into a filter, it's not advisable because the factory function will only ever be called once for a filter. The net result would therefore be to tie a particular filter to the scope it was first created with, which may not always be correct. As it turns out, it is not possible to inject scope into filters (or any service that is only ever created once), unless it is the root scope, which is essentially global to your application. Your intuition was correct that you should be passing in the values.</p> <p>I have updated the fiddle to include a custom filter:</p> <pre><code>myapp.filter('shouldShow', ['$filter', function ($filter) { var standardFilter = $filter('filter'); return function (widgets, showSubmitted, showInProgress) { return standardFilter(widgets, function (item) { var shouldShow = true; if (item.status === "submitted") shouldShow = shouldShow &amp;&amp; showSubmitted; if (item.status === "in progress") shouldShow = shouldShow &amp;&amp; showInProgress; return shouldShow; }); }; }]); </code></pre> <p>Basically this says inject the filter provider, then use it to load the filter filter (not a typo, just poor naming in angular). Then use the existing filter to implement our custom filter. I generally find this much easier than writing my own logic every time to loop through the elements and build the resulting array manually.</p> <p>This is a little complicated, in large part due to the poor filter naming, but this is just wrapping the existing filter filter to do exactly what we have already done in the previous code sample. <strong>I only recommend writing a custom filter if you intend to use it more than once in different scopes, otherwise the original function filter is still probably the best way to go.</strong></p>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload