1

New to Angular and, so far, I'm loving it but the learning curve seems pretty steep. What I want to do is wrap up a bit of simple business logic and build some re-usable DOM components to template common areas of my system. Specifically I am writing a simple survey application that has different question types. My goal is to get to the point that while I am in an ng-repeat block I can do something like this:

<div ng-repeat="question in questions">
     <show-question></show-question>
</div>

Ideally I want to wrap all of the logic into that one statement to switch on question type and then pull from templateUrl for different HTML sets. So if a question.type = "text" it would pull the templateUrl of "templates/textQuestion.html" and be able to inject scope into that template file as it produces the DOM element.

Big question is, am I going about this correctly AT ALL? Is a directive the way to go, should I even try to do this all in one directive/tag? I am open to being schooled on this!

Small question is, if I am going the right direction, what is the correct implementation?

I have already tried putting some logic inside my directives like IF and SWITCH, but that doesn't appear to be valid.

Any and all (constructive) help is welcome.

Thanks all!

2
  • I'd recommend reading the AngularJS docs. You can find very good tutorial videos here. Stackoverflow isn't really the place to ask such a broad question. Commented Feb 6, 2014 at 21:46
  • I've read the docs, and while they are very thorough, I've been having trouble figuring out how to interpret the examples into specific use cases (which is what I came to stack to learn). I wouldn't call the question broad, I gave a specific example and received some good very specific answers. I know I'm not the only one out there that is having a bit of trouble getting the "angular way" to socket into their brain housing group, it's just different enough (to me) that the docs don't always seem to make sense. Ask me in 6 months and I'm sure they will be easy to follow. Commented Feb 6, 2014 at 22:41

2 Answers 2

2

It's called a directive. There's a complete guide here: http://docs.angularjs.org/guide/directive

It allows you to make custom attributes, elements, CSS classes, and comments that turn into components.

I wouldn't pull separate templates for each question type, I'd use a different directive for each question type. Then you can switch between them using a parent directive.

Here is what a directive that loads different directives might look like:

app.directive('question', function($compile){
  "use strict";
  return{
    restrict: 'E',
    replace: true,
    link: function(scope, element, attrs){
      var render = function(){
        var template = "";
        switch(attrs.type){
          case "truefalse":
            template = '<truefalse></truefalse>';
          break;
          case "multiplechoice":
            template = '<multiplechoice></multiplechoice>';
          break;
          case "essay":
            template = '<essay></essay>';
          break;
        }
        element.html(template);
        $compile(element.contents())(scope);
      }

      attrs.$observe('type', function(value) {
          render();
      });
      render();
    }
  }; 
});

Now you could use this as such:

<question ng-repeat="question in questions" type="question.type" ></question>

Assuming you had a directive for each type of question, you'd get different directives rendered. This is sort of similar to using ng-if or different templates or whatever but I like it more because I also get re-usable one-off components.

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

2 Comments

Man, that is perfect! I basically dropped the code in place and it worked. What is more important than that, though, is that seeing it in action unlocked what I've been struggling with--I expect this to go a little more smoothly now. Gotta love a coding block. LOL I really wish the stack guys would let us give some extra points on a response just to say thanks.
You're welcome, and not that I'm asking for it, but you actually can give extra points by setting a bounty. Make sure to read up on "isolated scopes" and "encapsulation" as understanding those concepts will really help you architect re-usable components with Angular.
0

So if your scope variable questions has all the info for each question like

$scope.questions = [
  { type: 'input',
    prompt: 'name'
  }
];

Then you might have some html that looks like

<div question="question" ng-repeat="question in questions"></div>

And have a directive that looks something like

app.directive('question', function() {
  return {
    scope: {
      question: '=' // Creates 2 way data binding with the object you passed in as attribute by the same name
    },
    link: function($scope, $element, $attrs) {
        $scope.question; // This will be equal the object you passed in
        // { type: 'input', prompt: 'name' }
        // You can modify the dom or whatever here
    }
  };
});

If you want to have different prepared templates then you can inject the $templateCache into your directive

app.directive('question', function($templateCache) {

and then call them in your link function

link: function($scope, $element, $attrs) {
  var template = $templateCache.get('path/to/template.html');
  // and append it to the element
  $element.append(template);
}

You'll have to play around with it a bit, but that's half the fun. Good luck!

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.