Victor Hugo
Victor Hugo

Reputation: 109

select with ngOptions to select filter of another array

Edit: Plunker showing the problem: http://plnkr.co/edit/R5vNvejX3ncdqSzZst17?p=preview

Using AngularJS, I have a primary array that has tasks in it, like:

tasks.myTasks = [
    {task: "Task 1", done: "Y"}
    {task: "Task 2", done: "N"}
];

I want to set a select on the screen that have three options:

  1. Show all tasks.
  2. Show only done tasks.
  3. Show only undone tasks.

What I've done is set one array with the options, and one variable that is set to the filter when I'm ng-repeating myTasks:

tasks.filteringOptions = [
    "all": '',
    "only_done": {done: "Y"},
    "only_undone": {done: "N"}
];
tasks.filter = tasks.filteringOptions[0];

On my HTML I do my ng-repeat as follows:

<select ng-model="tasksCtrl.filter" ng-options="value as key for (key, value) in tasksCtrl.filteringOptions">
</select>

<div ng-repeat="task in tasksCtrl.myTasks | filter:tasksCtrl.filter">
   ...
</div>

Only problem is that the code above doesn't work, when the first item of the array is selected (all: '') it works fine, but I when I click the select and change it to one of the other options, it doesn't work.

To test it, I commented my select out of the HTML code and created an input:

<input ng-model="tasksCtrl.filter.done" type="text">

This approach worked fine, I type "Y" or "N" into the input and it filters myTasks as expected. So I figured the select was setting wrongly the tasksCtrl.filter, so I placed a div with the value of tasksCtrl.filter on top of the select and input and tested them both to see what I would get.

They both returned exactly the same result on my HTML:

{"done": "Y"}

I have tried to build my select with ng-repeat also, but I read online that it doesn't accept objects on it's value so I'm using ng-options instead.

I also noticed this: If I try to set the filter variable to {"done": "Y"}, when I'm using the input it works fine, the first results are already filtered, but if I place the select with the ng-options in it, the filter doesn't work anymore.

The final question is: Do I need to treat my object value to pass it into the ng-options? If not, how can the input and the select show the same result inside the variable tasksCtrl.filter and yet the select won't work as expected?

Upvotes: 0

Views: 445

Answers (2)

Suresh B
Suresh B

Reputation: 1652

// Code goes here

var app =angular.module('pof', []);
 


  app.controller('myController1', function(){
    var vm = this;
    
    vm.myTasks = [
      {'task': 'Task 1', 'done': 'Y'}, 
      {'task': 'Task 2', 'done': 'Y'}, 
      {'task': 'Task 3', 'done': 'Y'}, 
      {'task': 'Task 4', 'done': 'N'}, 
      {'task': 'Task 4', 'done': 'N'} 
    ];
    
    
    vm.filteringOptions = {
      'all': '',
      'only_done': {done: 'Y'},
      'only_undone': {done: 'N'}
    };
    
    vm.filter = vm.filteringOptions['only_done'];
  
  })

  app.controller('myController2', function($scope){
      $scope.statuses = [{
        id: 1,
        name: "First Value"        
    }, {
        id: 2,
        name: "Second Value"        
    }, {
        id: 3,
        name: "Third Value"        
    }, {
        id: 4,
        name: "Fourth Value"        
    }, {
        id: '',
        name: "All"        
    }];
    $scope.selected_status = 3;
     $scope.data = [
            { id: 1, name: "Max"},
            { id: 2, name: "Adam"},
            { id: 3, name: "Betty" },
            { id: 4, name: "Sara"  },
            { id: 5, name: "Arun"  }
            
        ];
  
  })

  app.directive('bsDropdown', function ($compile) {
    return {
        restrict: 'E',
        scope: {
            items: '=dropdownData',
            doSelect: '&selectVal',
            selectedItem: '=preselectedItem'
        },
        link: function (scope, element, attrs) {
            var html = '';
            switch (attrs.menuType) {
                case "button":
                    html += '<div class="btn-group"><button class="btn button-label btn-info">Action</button><button class="btn btn-info dropdown-toggle" data-toggle="dropdown"><span class="caret"></span></button>';
                    break;
                default:
                    html += '<div class="dropdown"><a class="dropdown-toggle" role="button" data-toggle="dropdown"  href="javascript:;">Dropdown<b class="caret"></b></a>';
                    break;
            }
            html += '<ul class="dropdown-menu"><li ng-repeat="item in items"><a tabindex="-1" data-ng-click="selectVal(item)">{{item.name}}</a></li></ul></div>';
            element.append($compile(html)(scope));
            for (var i = 0; i < scope.items.length; i++) {
                if (scope.items[i].id === scope.selectedItem) {
                    scope.bSelectedItem = scope.items[i];
                    break;
                }
            }
            scope.selectVal = function (item) {
                switch (attrs.menuType) {
                    case "button":
                        $('button.button-label', element).html(item.name);
                        break;
                    default:
                        $('a.dropdown-toggle', element).html('<b class="caret"></b> ' + item.name);
                        break;
                }
                scope.doSelect({
                    selectedVal: item.id
                });
            };
            scope.selectVal(scope.bSelectedItem);
        }
    };
});




  
<link href="http://st.pimg.net/cdn/libs/bootstrap/2.2/css/bootstrap.min.css" rel="stylesheet"/>
<script src="https://code.angularjs.org/1.4.8/angular.js"></script>
  <script src = "http://st.pimg.net/cdn/libs/jquery/1.8/jquery.min.js">
</script>
<script src = "http://st.pimg.net/cdn/libs/bootstrap/2/js/bootstrap.min.js">
</script>

   <body ng-app="pof">
  
    <div ng-controller="myController2 as myCtrl2">
      
<bs-dropdown data-menu-type="button" select-val="selected_status = selectedVal"
preselected-item="selected_status" data-dropdown-data="statuses"></bs-dropdown>  &nbsp; Selected Value : {{selected_status}}

<ul ng-repeat="item in data | filter: selected_status">
        <li>{{item.id}} {{item.name}}</li>
 </ul>
    </div>    
   
</body>
 

Upvotes: 0

Suresh B
Suresh B

Reputation: 1652

// Code goes here

var app =angular.module('myApp', []);
app.filter('custfilter', function(){
  
   
   return function(input, obj)
   {
     var val = JSON.stringify(obj);
     var inputval = JSON.stringify(input);
     //here use jquery to filter and return the data it will work
     return input;   
   }
})



  app.controller('myController1', function(){
    var vm = this;
    
    vm.myTasks = [
      {'task': 'Task 1', 'done': 'Y'}, 
      {'task': 'Task 2', 'done': 'Y'}, 
      {'task': 'Task 3', 'done': 'Y'}, 
      {'task': 'Task 4', 'done': 'N'}, 
      {'task': 'Task 4', 'done': 'N'} 
    ];
    
    
    vm.filteringOptions = {
      'all': '',
      'only_done': {done: 'Y'},
      'only_undone': {done: 'N'}
    };
    
    vm.filter = vm.filteringOptions['only_done'];
  
  })
  app.controller('myController2', function(){
    var vm = this;
    
    vm.myTasks = [
      {'task': 'Task 1', 'done': 'Y'}, 
      {'task': 'Task 2', 'done': 'Y'}, 
      {'task': 'Task 3', 'done': 'Y'}, 
      {'task': 'Task 4', 'done': 'N'}, 
      {'task': 'Task 4', 'done': 'N'} 
    ];
    
    
    vm.filteringOptions = {
      'all': {done: ''},
      'only_done': {done: 'Y'},
      'only_undone':{done: 'N'},
    };
    
    vm.filter = vm.filteringOptions['only_done'];
  
  })
;
<script src="https://code.angularjs.org/1.4.8/angular.js"></script>

    <script src="script.js"></script>


  <body ng-app="myApp">
    <div ng-controller="myController1 as myCtrl1">
      <h1>myController1: input (working)</h1>
      Here I am using a input below to filter myArray.<br/><br/>
      myTasks (filtered):
      <ul>
        <li ng-repeat="task in myCtrl1.myTasks | filter:myCtrl1.filter">Task: {{ task.task }} - Done? {{ task.done }} </li>  
      </ul>
      "filter.done" here, type here to see it changing correctly: <input type="text" ng-model="myCtrl1.filter">
      
    </div>
    <br/>
    <br/>
    <br/>
    <div ng-controller="myController2 as myCtrl2">
      <h1>myController2: select (not working)</h1>
      Here I have copied and pasted the same controller, identically stablished. But as you can see, it is showing nothing. <br/><br/>
      myTasks (won't show, choose "all" in the select below):
      <ul>
        <li ng-repeat="task in myCtrl2.myTasks | custfilter:myCtrl2.filter">Task: {{ task.task }} - Done? {{ task.done }} </li>  
      </ul>
      If you choose "all" it works, otherwise it won't work: <select ng-model="myCtrl2.filter" class="pull-right" ng-options="value as key for (key, value) in myCtrl2.filteringOptions"></select>
      
    </div>    
  </body>

Upvotes: 2

Related Questions