Question

I want to access a variable in this case map in the directive without having to predefine it like setting it as an attr of the directrive map="someValue". And also i dont want to use scope.$apply because i actually only want the variable in the isolated scope of the directive. Is this even possible ? What is the best practice here? Basically my directive needs to do both. Access the parent scope and have its own scope which with i can build the template with.

Thank you everybody.

Here my Js code:

.directive('myFilter', function() {
    return {
        restrict: 'E',
        scope: {
            source: '=source',
            key: '=key',
        },
        link: function(scope, element, attrs) {
            scope.$on('dataLoaded', function(e) { 
                scope.map = {};
                angular.forEach(scope.source, function(paramObj) {
                    if (!scope.map[paramObj[scope.key]]) {
                        var newEntry = {
                            value: paramObj[scope.key],
                            isChecked: false
                        }
                        scope.map[paramObj[scope.key]] = newEntry;
                    }
                });
            }); 
        }   
    }
});

and my html:

<my-filter source="metaPara.filteredParameters" key="'value'">
    <table class="table table-borered">
       <tr data-ng-repeat="item in map">
          <td>{{item.value}}</td>
        </tr>
    </table>
</my-filter>
Was it helpful?

Solution

You might want to refer to the Angular documentation for directives, again.

If you want an isolate-scope (a scope which has no access to ancestors), then use

scope : { /* ... */ }

otherwise, if you want a unique scope, which does have access to ancestors, use

scope : true

Then, you can put your HTML-modifying or event-listening (that doesn't rely on ng-click or something else Angular already covers) in

link : function (scope, el, attrs, controller) { }

...and you can put all of your regular implementation inside of

controller   : ["$scope", function ($scope) {
    var myController = this;
    myController.property = "12";
}],
controllerAs : "myController"

So that in your template you can say:

<span>{{ myController.property }}</span>

You can also use a pre-registered controller, which you call by name:

controller   : "mySimpleController",
controllerAs : "myController"

Also, rather than using $scope.$apply, I'd recommend using $timeout (has to be injected).

The difference is that $scope.$apply will only work at certain points -- if you're already inside of a digest cycle, it will throw an error, and not update anything.
$timeout( ) sets the updates to happen during the next update-cycle.

Ideally, you should know whether or not you need an $apply or not, and be able to guarantee that you're only using it in one spot, per update/digest, but $timeout will save you from those points where you aren't necessarily sure.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top