Injecting a HTML template to DOM on click the clean way (Create an instance of a class)?

christophe picture christophe · Oct 6, 2013 · Viewed 12.8k times · Source

In my AngularJS project I have something like this (it's a dropdown menu with customer names. With a click on one of the names a Scrum Card should appear with the customer's names inserted in the card.):

<ul class="dropdown-menu red" >
    <li ng-repeat="customer in customers" ng-click="addCard()">
        // HERE GOES THE HTML CODE
    </li>
</ul>

I want to accomplish that a card will be inserted on every click. Now the problem is, that this card has multiple lines of HTML code. So it would be better to insert a whole new template. But I can't insert a template with ng-click, right? Besides that, to put the HTML in a variable and push it to this list is quite dirty, isn't it?

So, I thought about creating a Card Class in Coffeescript and create an instance on every click. What would be good practive to create this class on click with my HTML template/partial? How do I tell Angular to create a new instance of my class Card?

(Before that I created a Directive that had the templateURL attribute with my partial. But the same problem: I want to inject my directive on ng-click and not manually by including my directive in the code ... btw, I am an Angular and CoffeeScript beginner ...)

Thank you very much in advance!

Answer

ksimons picture ksimons · Oct 6, 2013

You should, in my opinion, do two things. My apologies that this is JS and not CoffeeScript, but the intention is the same:

  1. Create a controller with a function that you call on ng-click. Maybe you already have this (since you don't show where addCard() is defined). This function should add an instance of your customer card class to an array which is bound into the $scope.
  2. If displaying one of these cards is sufficiently complex, make a new custom directive for displaying a card and use it inside your ng-repeat.

Example:

   <html>
    <head>
        <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.0.8/angular.min.js"></script>
        <script type="text/javascript">

        function Card() {
            this.name = 'Bob';
            this.phone = '1234567';
        }

        angular.module('myApp', []);

        angular.module('myApp').controller('CustomerCardController', function ($scope) {
            $scope.cards = [];

            $scope.addCard = function() {
                $scope.cards.push(new Card());
            };
        });

        angular.module('myApp').directive('myCard', function(){
            return {
                restrict: 'A',
                template: '<div>{{aCard.name}} {{aCard.phone}}</div>',
                replace: true,
                transclude: false,
                scope: {
                    aCard: '=myCard'
                }
            };
        });
        </script>
    </head>
    <body ng-app="myApp">
        <div ng-controller="CustomerCardController">
            <div ng-click="addCard()">Add new card</div>
            <div ng-repeat="card in cards" my-card="card"></div>
        </div>
    </body>
</html>