0

This question is based in the answer provided here

I want to output the result from a lodash function applied to a scope ($scope.names) when another scope ($scope.switch) is set to true, and to output the result of that lodash function applied to a filtered scope when $scope.switch is set to false.

So my ng-repeat would be like this:

<ul>
    <li ng-repeat="things in (filtered=(names | filter:filterType))">{{things}}</li>
</ul>

I use two ng-click to change the state of $scope.switch and to apply/unapply the filter:

<a ng-click="switch = false; filterType=''">unswitch - No Filters</a><br><br>
<a ng-click="switch = true; filterType={name:'!Jimmy'}">switch - Not Jimmy</a>

And I used this code in order to watch the changes in $scope.switch:

$scope.$watch('switch', function() {
      $scope.thingScope =$scope.switch ? _.map($scope.names,"styles") : _.map($scope.filtered,"styles");
    });

Here is the working plunkr with all the code (it's much easier to notice the problem here)

The problem is that the output of $scope.thingScope doesn't correspond to the values showed in the ng-repeat (right now every time I click, it shows the values of the previous one, that is, it goes one step behind). Thanks in advance!

Community
  • 1
  • 1
Joe82
  • 1,357
  • 2
  • 24
  • 40
  • I didn't get the problem with the filters and the `$scope.thingScope` Sorry. When you click the filter it doesn't show Jimmy data. What is the problem with it? – joseglego Jun 05 '16 at 21:23
  • @JoséLezama The output section should display the "styles" arrays from the filtered list section. If you check it now, when you click on switch, the filtered list displays three elements, while the output section displays two. This is not working as expected, as the output section is the result of applying the mapping function to the filtered scope (that should contain the elements displayed in the list). In summary, when in one part there is three elements, in the other should there be three as well. – Joe82 Jun 05 '16 at 21:28

2 Answers2

2

Ok, I found few problems.

0 - You are working with a generated list element (Filtered. which is the result of apply the filter over names). When the switch change, the generated list is not finished. So, you will not find the elements.

1 - You have a lot of elements Trying to work over the same (the Swtich/Filter over names).

2 - You are showing using: $scope.thingScope = $scope.switch ? _.map($scope.names,"styles") : _.map($scope.filtered,"styles"); So, you are showing $scope.names when $scope.switch == true. So wrong conditional.

3 - You are applying first the change of the switch and then the filterType in the ng-click.

So, you can do 2 things.

  1. Work with duplicated filters in 2 places (Not recommended.)
  2. The ng-repeat work with the processed-list. And work all the filters in the controller. As @shaunhusain did it.

P.S. I think it could be cleaner with an active to filter. And not by Name, check this Plnkr: http://plnkr.co/edit/4uJ5AxP9xntgBe1hQrBW?p=preview

You can select by Name (only clicking) but you must click again in update filters to apply changes.

joseglego
  • 2,011
  • 1
  • 17
  • 28
  • Thanks for your answer again! It clarified it a bit the matter for me. I will mark as correct the one by @shaunhusain though, it replies more directly to the problem exposed. – Joe82 Jun 06 '16 at 18:49
  • 1
    You can check my answer in other question about filters. Maybe it can help u: http://stackoverflow.com/questions/37661451/how-to-filter-objects-based-on-value-of-key-given-inside-same-object/37662398#37662398 – joseglego Jun 06 '16 at 18:56
1

Think your logic in the view is getting to the slightly heavy and not making sense due to all the watching that goes on with things bound in the view... this is easier to solve if you instead do it procedurally.

http://plnkr.co/edit/ZExywkLtDxuT82Ud6gYl?p=preview

<!DOCTYPE html>
<html>
  <head>
    <link rel="stylesheet" href="style.css">
    <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.9/angular.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.13.1/lodash.min.js"></script>
  </head>

  <body>
    <div ng-controller="myCtrl" ng-app="myApp">

      0. <b>Switch</b>: {{switch}} <br/><br/>
      1. <b>Output</b>: {{thingScope}} <br/><br/>
      2. <b>Filtered List</b>:
      <ul>
        <li ng-repeat="things in filtered">{{things}}</li>
      </ul>
      <a ng-click="changeSwitch(false, '')">unswitch - No Filters</a><br><br>
      <a ng-click="changeSwitch(true, {name:'!Jimmy'})">switch - Not Jimmy</a>
    </div>




    <script type="text/javascript">
      var app = angular.module('myApp', []);
      app.controller('myCtrl', function($scope, $filter) {
        $scope.switch = false;

        // set the default sort type
        $scope.filterType = '';

        var names=[{name:"Johny", styles:["one","two","three"]},{name:"Jimmy", styles:["two","three","four"]},{name:"Kevin", styles:["three","four","five"]}];

            // Option B:
        function filterData(searchObj){
          $scope.filtered = $filter('filter')(names, searchObj);
        };
        filterData();

        $scope.changeSwitch = function(newVal, filterType){
          $scope.switch = newVal;
          filterData(filterType);
          $scope.thingScope = !$scope.switch ? _.map(names,"styles") : _.map($scope.filtered,"styles");
        }

      });
    </script>
  </body>
</html>
shaunhusain
  • 19,630
  • 4
  • 38
  • 51
  • Your solution works fine, but I'm afraid that I need that logic in the view, as irl I have more filters applied to that ng-repeat. Thanks for the approach anyway! – Joe82 Jun 05 '16 at 20:31
  • 1
    @Joe82 you could still move those into a function as well but I understand it's easier to read the filters in the view than the $filter way of getting one, that said I think the underlying problem is the $watch gets triggered ahead of the filter but both are part of a digest, just difficult to control the order that all happens in from the view. – shaunhusain Jun 05 '16 at 20:32
  • yep, I think that's also the problem. I will wait if there is an alternative solution by modifying the $scope.$watch, and if not I will mark this as correct. – Joe82 Jun 05 '16 at 20:35
  • @Joe82 I think it work great. What is the problem with this one? The other filters will be about the others names too? You wanna filter by user? Or do you have other custom filters? – joseglego Jun 05 '16 at 21:34
  • @JoséLezama In my real application I have other 4 different filters attached to the ng-repeat and the scope has objects with more propieties. As I said, this solution works fine, but i don't think I am able to adapt it to the rest of the filters I have, so I was waiting if somebody can solve this issue in a more "Angular" way. – Joe82 Jun 05 '16 at 21:45
  • @Joe82 I have no more information about the real application. But you can check the plunkr to check if it can help you. I already made an answer – joseglego Jun 05 '16 at 23:14