0

I try to create general directive for filtering array in angular.

<body ng-controller="MainCtrl">
    controller: <input type="text" ng-model="query.name" /> - work<br>
    directive: <span filter by="name"></span> - not work
    <ul>
        <li ng-repeat="item in list | filter:query">{{item.name}}</li>
    </ul>
</body>

controller and directive are:

app.controller('MainCtrl', function($scope) {
    $scope.list = [
        {id: 1, name:'aaa'},
        {id: 2, name:'bbb'},
        {id: 3, name:'ccc'}
    ];
});

app.directive('filter', function () {
    return {
        scope: {
            by: '@'
        },
        link: function postLink(scope, element, attrs) {
            element.append(
                '<input type="text" ng-model="query.' + attrs.by + '">');
        }
    }
});

Filter in controller works but filter in directive doesn't. I don't know how to fix it.

Solution is fixed in plunker: http://plnkr.co/edit/WLGd6RPQEwMFRBvWslpt?p=preview

2
  • This is a very odd approach to filtering. Even if you could dynamically add elements like you're doing via link, query.name will never resolve inside your directive because you've isolated your scope (you'd have to use $parent.query.name, which isn't a good idea). Commented Apr 29, 2013 at 17:00
  • Yes this looks odd, because I simplified it more than was necessary. I used link because sometimes I need create <input type="text" another time <select><option>.... depend on list columns config. I tried to create general (universal) filter which doesn't know about data and create filter depend on meta data from config array. Commented Apr 29, 2013 at 19:13

1 Answer 1

1

Since you have isolated the scopes you have to use eiter $parent or you have to set up two way binding using '=' i have update your example with two way binding

<!doctype html>
<html ng-app="plunker" >
<head>
  <meta charset="utf-8">
  <title>AngularJS Plunker</title>
  <script>document.write('<base href="' + document.location + '" />');</script>
  <link rel="stylesheet" href="style.css">
  <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.0.5/angular.js"></script>
  <script src="app.js"></script>
</head>
<body ng-controller="MainCtrl">
  controller: <input type="text" ng-model="query.name" /> - work<br>
  directive: <span filter by="query"></span> - not work
      <ul>
        <li ng-repeat="item in list | filter:query">{{item.name}}</li>
    </ul>
    <script>
        var app = angular.module('plunker', []);

        app.controller('MainCtrl', function ($scope) {
            $scope.list = [
              { id: 1, name: 'aaa' },
              { id: 2, name: 'bbb' },
              { id: 3, name: 'ccc' }
            ];
            alert("123");
            $scope.query = { name: "" }
        });

        app.directive('filter', function () {
            return {
                scope: {
                    by: '='
                },
                replace: true,
                template:'<input ng-model="by.name"></input>'

            }
        });
    </script>
</body>

</html>
Sign up to request clarification or add additional context in comments.

2 Comments

thanks, but you used name inside in directive. But I need to create general directive, which doesn't know about columns of data. So my primary problem is how to pass column name in variable. Now it is name but for other dataset will be anything else
@MarekL then you just need to specify by="query.name" and change your directive to say ng-model="by": jsfiddle.net/SCvJn

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.