Rectangle 27 11

Both answers were good so I moved them in to a directive so that it is reusable and a second scope variable doesn't have to be defined.

Here is the fiddle if you want to see it implemented

var uniqueItems = function (data, key) {
    var result = [];
    for (var i = 0; i < data.length; i++) {
        var value = data[i][key];
        if (result.indexOf(value) == -1) {
            result.push(value);
        }
    }
    return result;
};

myApp.filter('groupBy',
            function () {
                return function (collection, key) {
                    if (collection === null) return;
                    return uniqueItems(collection, key);
        };
    });

Then it can be used as follows:

<div ng-repeat="team in players|groupBy:'team'">
    <b>{{team}}</b>
    <li ng-repeat="player in players | filter: {team: team}">{{player.name}}</li>        
</div>

Which "both" answers? There are many now.

javascript - How can I group data with an Angular filter? - Stack Over...

javascript filter angularjs grouping
Rectangle 27 42

Accessing controller method means accessing a method on parent scope from directive controller/link/scope.

If the directive is sharing/inheriting the parent scope then it is quite straight forward to just invoke a parent scope method.

Little more work is required when you want to access parent scope method from Isolated directive scope.

There are few options (may be more than listed below) to invoke a parent scope method from isolated directives scope or watch parent scope variables (option#6 specially).

Note that I used link function in these examples but you can use a directive controller as well based on requirement.

Through Object literal and from directive html template

Option#2. Through Object literal and from directive link/scope

Option#3. Through Function reference and from directive html template

Option#4. Through Function reference and from directive link/scope

Option#5: Through ng-model and two way binding, you can update parent scope variables.

index.html
itemfilterTemplate.html
<select ng-model="selectedItems" multiple="multiple" style="height: 200px; width: 250px;" 
 ng-options="item.id as item.name group by item.model for item in items | orderBy:'name'">
  <option>--</option>
</select>
app.js
var app = angular.module('plunker', []);

app.directive('sdItemsFilter', function() {
  return {
    restrict: 'E',
    scope: {
      items: '=',
      selectedItems: '=ngModel'
    },
    templateUrl: "itemfilterTemplate.html"
  }
})

app.controller('MainCtrl', function($scope) {
  $scope.name = 'TARS';

  $scope.selectedItems = ["allItems"];

  $scope.items = [{
    "id": "allItems",
    "name": "All Items",
    "order": 0
  }, {
    "id": "CaseItem",
    "name": "Case Item",
    "model": "PredefinedModel"
  }, {
    "id": "Application",
    "name": "Application",
    "model": "Bank"
    }]
});

Option#6: Through $watch and $watchCollection It is two way binding for items in all above examples, if items are modified in parent scope, items in directive would also reflect the changes.

If you want to watch other attributes or objects from parent scope, you can do that using $watch and $watchCollection as given below

<!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 data-require="angular.js@1.3.x" src="https://code.angularjs.org/1.3.9/angular.js" data-semver="1.3.9"></script>
  <script src="app.js"></script>
</head>

<body ng-controller="MainCtrl">
  <p>Hello {{user}}!</p>
  <p>directive is watching name and current item</p>
  <table>
    <tr>
      <td>Id:</td>
      <td>
        <input type="text" ng-model="id" />
      </td>
    </tr>
    <tr>
      <td>Name:</td>
      <td>
        <input type="text" ng-model="name" />
      </td>
    </tr>
    <tr>
      <td>Model:</td>
      <td>
        <input type="text" ng-model="model" />
      </td>
    </tr>
  </table>

  <button style="margin-left:50px" type="buttun" ng-click="addItem()">Add Item</button>

  <p>Directive Contents</p>
  <sd-items-filter ng-model="selectedItems" current-item="currentItem" name="{{name}}" selected-items-changed="selectedItemsChanged" items="items"></sd-items-filter>

  <P style="color:red">Selected Items (in parent controller) set to: {{selectedItems}}</p>
</body>

</html>
app.directive('sdItemsFilter', function() {
  return {
    restrict: 'E',
    scope: {
      name: '@',
      currentItem: '=',
      items: '=',
      selectedItems: '=ngModel'
    },
    template: '<select ng-model="selectedItems" multiple="multiple" style="height: 140px; width: 250px;"' +
      'ng-options="item.id as item.name group by item.model for item in items | orderBy:\'name\'">' +
      '<option>--</option> </select>',
    link: function(scope, element, attrs) {
      scope.$watchCollection('currentItem', function() {
        console.log(JSON.stringify(scope.currentItem));
      });
      scope.$watch('name', function() {
        console.log(JSON.stringify(scope.name));
      });
    }
  }
})

 app.controller('MainCtrl', function($scope) {
  $scope.user = 'World';

  $scope.addItem = function() {
    $scope.items.push({
      id: $scope.id,
      name: $scope.name,
      model: $scope.model
    });
    $scope.currentItem = {};
    $scope.currentItem.id = $scope.id;
    $scope.currentItem.name = $scope.name;
    $scope.currentItem.model = $scope.model;
  }

  $scope.selectedItems = ["allItems"];

  $scope.items = [{
    "id": "allItems",
    "name": "All Items",
    "order": 0
  }, {
    "id": "CaseItem",
    "name": "Case Item",
    "model": "PredefinedModel"
  }, {
    "id": "Application",
    "name": "Application",
    "model": "Bank"
  }]
});

You can always refer AngularJs documentation for detailed explanations about directives.

I answered the question with all available alternatives with clear separation. In my opinion, short answers are not always helpful until you have a big picture in front of you.

@YogeshManware: It could be shortened a lot by leaving out the irrelevant stuff like stylesheets, not using lengthy markup, simplifying the examples to not use things like "group by", etc. It would also be very useful with some sort of explanation for each example.

How to access parent scope from within a custom directive *with own sc...

angularjs angularjs-directive
Rectangle 27 41

Accessing controller method means accessing a method on parent scope from directive controller/link/scope.

If the directive is sharing/inheriting the parent scope then it is quite straight forward to just invoke a parent scope method.

Little more work is required when you want to access parent scope method from Isolated directive scope.

There are few options (may be more than listed below) to invoke a parent scope method from isolated directives scope or watch parent scope variables (option#6 specially).

Note that I used link function in these examples but you can use a directive controller as well based on requirement.

Through Object literal and from directive html template

Option#2. Through Object literal and from directive link/scope

Option#3. Through Function reference and from directive html template

Option#4. Through Function reference and from directive link/scope

Option#5: Through ng-model and two way binding, you can update parent scope variables.

index.html
itemfilterTemplate.html
<select ng-model="selectedItems" multiple="multiple" style="height: 200px; width: 250px;" 
 ng-options="item.id as item.name group by item.model for item in items | orderBy:'name'">
  <option>--</option>
</select>
app.js
var app = angular.module('plunker', []);

app.directive('sdItemsFilter', function() {
  return {
    restrict: 'E',
    scope: {
      items: '=',
      selectedItems: '=ngModel'
    },
    templateUrl: "itemfilterTemplate.html"
  }
})

app.controller('MainCtrl', function($scope) {
  $scope.name = 'TARS';

  $scope.selectedItems = ["allItems"];

  $scope.items = [{
    "id": "allItems",
    "name": "All Items",
    "order": 0
  }, {
    "id": "CaseItem",
    "name": "Case Item",
    "model": "PredefinedModel"
  }, {
    "id": "Application",
    "name": "Application",
    "model": "Bank"
    }]
});

Option#6: Through $watch and $watchCollection It is two way binding for items in all above examples, if items are modified in parent scope, items in directive would also reflect the changes.

If you want to watch other attributes or objects from parent scope, you can do that using $watch and $watchCollection as given below

<!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 data-require="angular.js@1.3.x" src="https://code.angularjs.org/1.3.9/angular.js" data-semver="1.3.9"></script>
  <script src="app.js"></script>
</head>

<body ng-controller="MainCtrl">
  <p>Hello {{user}}!</p>
  <p>directive is watching name and current item</p>
  <table>
    <tr>
      <td>Id:</td>
      <td>
        <input type="text" ng-model="id" />
      </td>
    </tr>
    <tr>
      <td>Name:</td>
      <td>
        <input type="text" ng-model="name" />
      </td>
    </tr>
    <tr>
      <td>Model:</td>
      <td>
        <input type="text" ng-model="model" />
      </td>
    </tr>
  </table>

  <button style="margin-left:50px" type="buttun" ng-click="addItem()">Add Item</button>

  <p>Directive Contents</p>
  <sd-items-filter ng-model="selectedItems" current-item="currentItem" name="{{name}}" selected-items-changed="selectedItemsChanged" items="items"></sd-items-filter>

  <P style="color:red">Selected Items (in parent controller) set to: {{selectedItems}}</p>
</body>

</html>
app.directive('sdItemsFilter', function() {
  return {
    restrict: 'E',
    scope: {
      name: '@',
      currentItem: '=',
      items: '=',
      selectedItems: '=ngModel'
    },
    template: '<select ng-model="selectedItems" multiple="multiple" style="height: 140px; width: 250px;"' +
      'ng-options="item.id as item.name group by item.model for item in items | orderBy:\'name\'">' +
      '<option>--</option> </select>',
    link: function(scope, element, attrs) {
      scope.$watchCollection('currentItem', function() {
        console.log(JSON.stringify(scope.currentItem));
      });
      scope.$watch('name', function() {
        console.log(JSON.stringify(scope.name));
      });
    }
  }
})

 app.controller('MainCtrl', function($scope) {
  $scope.user = 'World';

  $scope.addItem = function() {
    $scope.items.push({
      id: $scope.id,
      name: $scope.name,
      model: $scope.model
    });
    $scope.currentItem = {};
    $scope.currentItem.id = $scope.id;
    $scope.currentItem.name = $scope.name;
    $scope.currentItem.model = $scope.model;
  }

  $scope.selectedItems = ["allItems"];

  $scope.items = [{
    "id": "allItems",
    "name": "All Items",
    "order": 0
  }, {
    "id": "CaseItem",
    "name": "Case Item",
    "model": "PredefinedModel"
  }, {
    "id": "Application",
    "name": "Application",
    "model": "Bank"
  }]
});

You can always refer AngularJs documentation for detailed explanations about directives.

I answered the question with all available alternatives with clear separation. In my opinion, short answers are not always helpful until you have a big picture in front of you.

@YogeshManware: It could be shortened a lot by leaving out the irrelevant stuff like stylesheets, not using lengthy markup, simplifying the examples to not use things like "group by", etc. It would also be very useful with some sort of explanation for each example.

How to access parent scope from within a custom directive *with own sc...

angularjs angularjs-directive
Rectangle 27 41

Accessing controller method means accessing a method on parent scope from directive controller/link/scope.

If the directive is sharing/inheriting the parent scope then it is quite straight forward to just invoke a parent scope method.

Little more work is required when you want to access parent scope method from Isolated directive scope.

There are few options (may be more than listed below) to invoke a parent scope method from isolated directives scope or watch parent scope variables (option#6 specially).

Note that I used link function in these examples but you can use a directive controller as well based on requirement.

Through Object literal and from directive html template

Option#2. Through Object literal and from directive link/scope

Option#3. Through Function reference and from directive html template

Option#4. Through Function reference and from directive link/scope

Option#5: Through ng-model and two way binding, you can update parent scope variables.

index.html
itemfilterTemplate.html
<select ng-model="selectedItems" multiple="multiple" style="height: 200px; width: 250px;" 
 ng-options="item.id as item.name group by item.model for item in items | orderBy:'name'">
  <option>--</option>
</select>
app.js
var app = angular.module('plunker', []);

app.directive('sdItemsFilter', function() {
  return {
    restrict: 'E',
    scope: {
      items: '=',
      selectedItems: '=ngModel'
    },
    templateUrl: "itemfilterTemplate.html"
  }
})

app.controller('MainCtrl', function($scope) {
  $scope.name = 'TARS';

  $scope.selectedItems = ["allItems"];

  $scope.items = [{
    "id": "allItems",
    "name": "All Items",
    "order": 0
  }, {
    "id": "CaseItem",
    "name": "Case Item",
    "model": "PredefinedModel"
  }, {
    "id": "Application",
    "name": "Application",
    "model": "Bank"
    }]
});

Option#6: Through $watch and $watchCollection It is two way binding for items in all above examples, if items are modified in parent scope, items in directive would also reflect the changes.

If you want to watch other attributes or objects from parent scope, you can do that using $watch and $watchCollection as given below

<!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 data-require="angular.js@1.3.x" src="https://code.angularjs.org/1.3.9/angular.js" data-semver="1.3.9"></script>
  <script src="app.js"></script>
</head>

<body ng-controller="MainCtrl">
  <p>Hello {{user}}!</p>
  <p>directive is watching name and current item</p>
  <table>
    <tr>
      <td>Id:</td>
      <td>
        <input type="text" ng-model="id" />
      </td>
    </tr>
    <tr>
      <td>Name:</td>
      <td>
        <input type="text" ng-model="name" />
      </td>
    </tr>
    <tr>
      <td>Model:</td>
      <td>
        <input type="text" ng-model="model" />
      </td>
    </tr>
  </table>

  <button style="margin-left:50px" type="buttun" ng-click="addItem()">Add Item</button>

  <p>Directive Contents</p>
  <sd-items-filter ng-model="selectedItems" current-item="currentItem" name="{{name}}" selected-items-changed="selectedItemsChanged" items="items"></sd-items-filter>

  <P style="color:red">Selected Items (in parent controller) set to: {{selectedItems}}</p>
</body>

</html>
app.directive('sdItemsFilter', function() {
  return {
    restrict: 'E',
    scope: {
      name: '@',
      currentItem: '=',
      items: '=',
      selectedItems: '=ngModel'
    },
    template: '<select ng-model="selectedItems" multiple="multiple" style="height: 140px; width: 250px;"' +
      'ng-options="item.id as item.name group by item.model for item in items | orderBy:\'name\'">' +
      '<option>--</option> </select>',
    link: function(scope, element, attrs) {
      scope.$watchCollection('currentItem', function() {
        console.log(JSON.stringify(scope.currentItem));
      });
      scope.$watch('name', function() {
        console.log(JSON.stringify(scope.name));
      });
    }
  }
})

 app.controller('MainCtrl', function($scope) {
  $scope.user = 'World';

  $scope.addItem = function() {
    $scope.items.push({
      id: $scope.id,
      name: $scope.name,
      model: $scope.model
    });
    $scope.currentItem = {};
    $scope.currentItem.id = $scope.id;
    $scope.currentItem.name = $scope.name;
    $scope.currentItem.model = $scope.model;
  }

  $scope.selectedItems = ["allItems"];

  $scope.items = [{
    "id": "allItems",
    "name": "All Items",
    "order": 0
  }, {
    "id": "CaseItem",
    "name": "Case Item",
    "model": "PredefinedModel"
  }, {
    "id": "Application",
    "name": "Application",
    "model": "Bank"
  }]
});

You can always refer AngularJs documentation for detailed explanations about directives.

I answered the question with all available alternatives with clear separation. In my opinion, short answers are not always helpful until you have a big picture in front of you.

@YogeshManware: It could be shortened a lot by leaving out the irrelevant stuff like stylesheets, not using lengthy markup, simplifying the examples to not use things like "group by", etc. It would also be very useful with some sort of explanation for each example.

How to access parent scope from within a custom directive *with own sc...

angularjs angularjs-directive
Rectangle 27 0

This is because the filter is available to the 'exampleApp' module since it is a dependency.

Adam Thomas is correct about that, but it is a common scenario to depend on custom directives, services, and filters in other custom items. You want to make things explicit in your DI assertions. This will cause things to break at the injection level instead of when using the custom directive in this case.

//DIRECTIVE
angular.module('directives',['services']).directive('linkBox', ['toDate',function(toDate){
  ...
}]);

With this you can be clear about what you need to use the directive and will not be easily missed. This may require you to tweak how you declare 'toDate'.

Erstad - The code example listed in this answer will not work as typed. See my post for the reason.

Good call. Thanks for correcting it.

angularjs - Access to custom filter from an Angular directive with iso...

angularjs angularjs-directive angularjs-scope angularjs-filter
Rectangle 27 0

I'm not aware if Angular has a service to strip html, but it seems you need to remove html before passing your newlines custom filter. The way I would do it is through a custom no-html directive, which would be passed a scope property and the name of a filter to apply after removing the html

<div no-html="data" post-filter="newlines"></div>
app.directive('noHtml', function($filter){
  return function(scope, element, attrs){
    var html = scope[attrs.noHtml];
    var text = angular.element("<div>").html(html).text();

    // post filter
    var filter = attrs.postFilter;
    var result = $filter(filter)(text);

    // apending html
    element.html(result);
  };
});

The important bit is the text variable. Here I create an intermediate DOM element and append it the HTML using the html method and then retrieve only the text with the text method. Both methods are provided by Angular's lite version of jQuery.

The following part is applying the newline filter, which is done using the $filter service.

javascript - angularjs newline filter with no other html - Stack Overf...

javascript html angularjs sanitization
Rectangle 27 0

So, when I use one-way binding i got empty array in $watch (i think it's trying evaluate in local scope [removed "data" from directive scope for one way binding]. When i use two way binding [in directive scope is {data: "=data"}] i got error "Watchers fired in the last 5 iterations" (it's common error for filtering in angular).

...
scope: {
  data: "=data"
}
...
link: function (scope, element, attrs, ctrl) {
  ...
  scope.$watch("data", function (newValue) {
    angular.forEach(newValue, function (v, i) {
      model.add(v);
    }
  }
}
...
...
  $scope.filter = { a:true, b:false, ... };
  $scope.all = [..data..];
  $scope.visible = [..data..];    

  $scope.$watch("filter", function(newValue) {    
    $scope.visible = $scope.$eval("all | orFilter:filter"); 
  }, true);
  ...
<div my-module data="visible"></div>

Thank you very much guys, you're help me so much. I'm learned many new things about angular binding.

angularjs - Angular custom directive with filter in attribute - Stack ...

angularjs angularjs-directive angularjs-filter
Rectangle 27 0

This is because the directive is a child of the root scope created by the exampleApp module. The services, controllers, and directives modules are injected into exampleApp giving prototypical inheritance up the tree from child to root scope. It is dangerous to rely on the toDate filter being accessible to the linkBox directive in case at some point in the future the root scope created by exampleApp were to exclude the services module.

What Erstad Stephen wrote in his answer is partially correct, but his example won't work as it is typed since the $injector requires filter names to have a suffix of Filter. As is detailed in the $filterProvider docs.

The following code works:

//CORE MODULE
angular.module('exampleApp',['controllers','directives']);

angular.module('controllers',[]).controller('app_ctrl',['$scope',function($scope){
  $scope.dateVal = 20131010;
}]);

angular.module('services',[]).filter('toDate',[function(){
  function func(ymd){
    ymd = ymd + "";
    var y = ymd.substring(0,4);
    var m = ymd.substring(4,6);
    var d = ymd.substring(6);
    return (+m) + "/" + (+d) + "/" + y;
  }
  return func;
}]);

//DIRECTIVE
angular.module('directives',['services']).directive('linkBox', ['toDateFilter', function(toDate){
  var dir = {
    transclude:false,
    scope:{isolateVar:'@linkBox'},
    replace:true,
    template:'<p>Filtered value: {{isolateVar | toDate}}</p>',
    link: function lfn(scope, instance, attr){
      var a = angular.element(instance); 
      a.text(scope.isolateVar.name);
      console.log(scope);
    } //end link function
  }; //end dir object
  return dir;
}]);

I dig it. Give him the answer!

angularjs - Access to custom filter from an Angular directive with iso...

angularjs angularjs-directive angularjs-scope angularjs-filter