0

My custom directive runs fine onload page load but when added using append it does not run properly. It does not show its content when at in runtime.

HTML:

<!doctype html>
<html lang="en" ng-app="module1">
<head>
  <meta charset="UTF-8">
  <title>Angular Demo</title>

  <link rel="stylesheet" href="css/bootstrap.css">    

  <script src="js/angular.js"></script>
  <script src="js/ui-bootstrap-tpls-0.13.0.js"></script>    
  <script src="js/app.js"></script>
</head>
<body>

<div id="divContainer" style="border-style: solid;border-color:red;" ng-controller = "Controller1 as cnt1" >
    <button ng-click="clicked();">Click Me!!</button> 
    <wlaccordion></wlaccordion>
</div>        

</body>
</html>

app.js:

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

app.controller('Controller1', ['$scope', function($scope) {

    $scope.authorData = authorInfo;

    $scope.clicked = function () {
        alert('Clicked');
        //angular.element(document.getElementById('divContainer')).append('<wlaccordion1></wlaccordion1>' (scope));
        angular.element(document.getElementById('divContainer')).append('<wlaccordion></wlaccordion>');
    }

}]);//controller1    

var authorInfo = [
    {
        'name': 'Ray',
        'rate': '10',
        'show': 'true'    
    },
    {
        'name': 'Mahesh',
        'rate': '12',        
        'show': 'true'    
    }
]

app.directive("wlaccordion", function($compile) {

    var template = '<div ng-controller = "Controller1 as cnt1">' +   
                        '<div ng-repeat="aData in authorData" ng-init="tab = 1">' +    
                            '<ul>' +
                                '<li>' +
                                    '<h1 ng-show={{aData.show}} ng-class="{active: tab === 1}"> {{aData.name}} </h1>' +                
                                    '<h1 ng-show={{aData.show}} ng-class="{active: tab === 2}"> {{aData.rate | currency}} </h1>' +
                                '</li>' +
                            '</ul>' +
                        '</div>' +
                    '</div>';            

    return{
        link: function(scope, element){
                    var content = $compile(template)(scope);
                    element.append(content);
        }
    }
});

I would like the directive to function same as onload.

-Thanks Mahesh

6
  • 3
    .append is a very un-Angular thing to do. You should use ng-if to toggle your accordion instead Commented May 29, 2015 at 13:44
  • @RGraham I will be getting fresh data in JSON format based on which I need to rebuild the view. Right now I have just put static data. Commented May 29, 2015 at 13:48
  • Why are you compiling the code in link function instead of using template property of directive? Commented May 29, 2015 at 13:48
  • I tried various combinations, none worked, even this one does not work when added element is appended. I just need a way to show the <wlaccordion> directive using element append as it shows on document load. Commented May 29, 2015 at 13:49
  • You can't just append a directive. It needs to be compiled (check out $compile: code.angularjs.org/1.3.14/docs/api/ng/service/$compile). That said, @RGraham is correct. Don't manipulate the DOM in your controller!!! code.angularjs.org/1.3.14/docs/guide/controller. Use a built in directive such as ng-include or ng-if, or create your own. Commented May 29, 2015 at 13:56

2 Answers 2

1

AngularJS intended for separation of presentation logic and business one. So I think you should do this in Angular way, your current approach is more jQuery one.

I would suggest you to add accordions collection to controller:

app.controller('Controller1', ['$scope', function($scope) {
    $scope.accordions = [0]; // Replace 0 with some actual data
    $scope.clicked = function() {
        $scope.accordions.push($scope.accordions.length); // Same here
    };
    // Your other code
}

And in HTML add ng-repeat:

<div id="divContainer" style="border-style: solid;border-color:red;" ng-controller = "Controller1 as cnt1" >
    <button ng-click="clicked();">Click Me!!</button> 
    <wlaccordion ng-repeat="accordion in accordions"></wlaccordion>
</div>  

Edit: Also don't forget to remove compilation from wlaccordion's link.

Edit #2: I suppose that authorInfo global var is used simply for example, however if it doesn't then consider usage of module.constant or module.value

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

5 Comments

Thanks, I'll restructure my code. What I am wondering is why the custom directive not showing up properly even though $compile was used without link.
Because that link function was never executed - angluar had no idea that you've added that directive (because you've made it through jQuery). You should've executed compilation in parent code: angular.element(...).append($compile('<wlaccordion/>')($scope)). Just to make it clear: angular have no idea about any DOM manipulation you are doing through jQuery.
when I do that I get exception: ReferenceError: $compile is not defined
Do you have it declared in controller's dependencies?
Finally got it working, Thanks for your help. Dependency was missing.
0
app.controller('Controller1', ['$scope','$compile', function($scope, $compile) {

    $scope.authorData = authorInfo;

    $scope.clicked = function () {
        alert('Clicked');
        //angular.element(document.getElementById('divContainer')).append('<wlaccordion1></wlaccordion1>' (scope));
        angular.element(document.getElementById('divContainer')).append($compile('<wlaccordion></wlaccordion>')($scope));
    }

}]);//controller1 

Comments

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.