1

I just started using AngularJS and immediately ran into a problem:

I have a sidebar which contains "action-buttons" - depending on the currently active view, different buttons should be visible.

My view-controller defines an object which looks as follows:

$scope.sidebar.actionButtons = [
            {   icon: "plus",  label: "Add",    enabled: true,  url: "customer.new" },
            {   icon: "minus", label: "Delete", enabled: false, action: function(){ alert("Not implemented yet"); }}
        ];

As you can see, there are two different kinds of action-buttons: Either the button changes to another view (url is set to customer.new), or the button triggers an arbitrary function (action is set to alert()).

Each button type has to generate some slightly different html, and I'm not able to get this working.


After playing around for several hours, here is my current (not-working) approach:

My sidebar uses the following template-code to generate the buttons:

<ul class="nav" id="sidebar-action-buttons">
    <action-button ng-repeat="button in actionButtons" button="button"/>
</ul>

Now, the actionButton directive has everything it needs and should produce the html depending on the button type:

angular.module('myApp')
    .directive('actionButton', function($compile) {
        function linker($scope, $element, $attrs){
            var innerHtml = '';
            $element.attr('ng-class', '{disabled: !button.enabled}');

            if($scope.button.url) {
                $element.attr('ui-sref-active', 'active')
                innerHtml = '<a ui-sref="{{button.url}}">';
            } else {
                innerHtml = '<a ng-click="button.action()">';
            }
            innerHtml += '{{button.label}}</a>';

            $element.html(innerHtml).show();
            $compile($element.contents())($scope);
        }

        return {
            restrict: 'E',
            replace: true,
            scope: { button: "=" },
            link: linker,
            template: "<li></li>"
        }
    });

This generates the correct content. The problem here is, that the attributes which are placed on the actionButton element (in this case ng-class='{disabled: !button.enabled}') are not compiled.


How can a directive produce different html depending on scope variables? What is the correct approach for doing this? How can I also compile the newly added attributes?

2 Answers 2

2

By the time the ng-class is added to the action-button element, the digest is over with for that element. You could call $scope.$apply(), but I would add the ng-class to each anchor element instead, then there would be no need to call $scope.$apply() again.

Sign up to request clarification or add additional context in comments.

6 Comments

I can definitly add the ng-class in the sidebar-template. However, the action-button directive would not be self-contained anymore and I want to avoid that if possible. $scope.$apply() can't be called within the link function.
I'm using this solution for now, but there has to be a better alternative.
If you added ng-class in the inner html along with the ui-sref and ng-click, the directive would still be self-contained.
That's correct, but my html looks as follows: <ul><li><a/></li> ... </ul>, where li is the action button. I want the ng-click to be applied to <a> and the ng-class to <li>.
Oh, I see. I think you should just forget about the directive and have them all have ng-click to a function that then does an if statement, one does $state.go and the other calls that arbitrary function. You would have to send the button object to the controller, but that's okay.
|
0

Because you are compiling content() of the li but ng-class has been added with li itself. Simple solution is to add ng-class directly with the action-button directive i.e.

<action-button ng-repeat="button in actionButtons" button="button" ng-class="{disabled: !button.enabled}"  />

1 Comment

That's a possible solution (also recommended by cabey77), but as I mentioned in the comments there, the action-button directive would not be self-contained anymore and I want to avoid that if possible.

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.