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

12,914

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>
Share:
12,914
christophe
Author by

christophe

Updated on July 29, 2022

Comments

  • christophe
    christophe almost 2 years

    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!

  • christophe
    christophe over 10 years
    Thank you for your answer! This is an attempt I have done before. But my problem is HOW to push the cards in the my-card (or whatever) directive, since it includes several lines of HTML code. I thought of a better approach like inserting a whole template on click, but don't know how to fetch it.
  • christophe
    christophe over 10 years
    Thank you for your extented answer – it really helped me!
  • ksimons
    ksimons over 10 years
    Glad it helped. I cleaned up the example a little bit by removed the card attribute (which was redundant) and just using the directive attribute (my-card, a.k.a. myCard) directly.
  • christophe
    christophe over 10 years
    If you don't mind, I have another question. Now I face another problem: I have different type of cards, 5 in total. So each card's templates differ in one class, the color. So now I would make 5 directives, but when I do this, the cards don't push in card's array properly. Within in the controller I am also not able (and shouldn't) to manipulate the DOM with jQuery to change the class. Do you have any suggestion to administrate 5 different templates with diretives and push them all in the same array? With the current code I am not able to add just one of those 5 cards each time I click.
  • ksimons
    ksimons over 10 years
    You should have a property on your cards representing their color. Then use, for example, ng-class inside your ONE directive's template to pick the color. So for example on if your card has a .color property, you could do: <div ng-class="card-{{aCard.color}}>{{aCard.name}} {{aCard.phone}}</div> and then in your CSS define classes .card-green, .card-blue, etc. or whatever values you set your .color property to.
  • christophe
    christophe over 10 years
    Great approach!! Thank u so much, Kevin! :)