0

I have an angular app that shows a list of things

<div ng-repeat="thing in things" regular-thing>

implemented with an ng-repeat that shows a regularThing directive for each thing in my list.

It's actually a little bit trickier than that though:

<div ng-repeat-start="thing in things">
    <div ng-if="$first || thing.isSpecial" special-thing></div>
    <div ng-if="!$first && !thing.isSpecial" regular-thing></div>
</div>
<div ng-repeat-end></div>

I use a different directive for the first thing in my list, and also for any "special" things. For our purposes, a thing becomes "special" when the user clicks on it - so, as they're scrolling through the list, they can click on a thing to have it displayed in a different (more extensive) template.

The way I have it now feels wrong to me. For one thing, I really don't need to have two different directives - just different templates. The logic is identical, specialThing just has a bit more of it. For another thing, I'm toggling a property on the data (namely thing.isSpecial) for purely view-related reasons, which makes me die a little bit inside.

So my question: Don't I deserve to die a little bit inside for this? Isn't there a cleaner, more "angular" way to handle this (i.e. to toggle between the directive templates)?

drew moore
  • 31,565
  • 17
  • 75
  • 112
  • 1
    Depending on the template differences, it might be better if you use the show/hide feature on some of the DOM elements whenever one of your components is clicked. If you could show us the templates it might be easier to see if that is an option. – Eyal Mar 08 '15 at 05:42
  • @Eyal - it's a good suggestion, thanks. Unfortunately, it's one I've already considered and decided against because the differences are dramatic, there were so many shows and hides and switches that it ended up feeling cleaner to do it as described above – drew moore Mar 08 '15 at 06:35
  • 1
    There's a similar problem that was solved here, and might give you some ideas: http://stackoverflow.com/questions/22448143/how-to-make-a-list-and-grid-view-toggle-switch-control-that-loads-in-partials-in I hope that helps. If I think of something else, I'll let you know :) – Eyal Mar 08 '15 at 07:22

1 Answers1

0

First, no one deserves do die. So the answer to your question is "no".

But you do raise some interesting points.

First, it's ok to have "view model" information in your scope (or controller, depending on if you are using the ControllerAs syntax or not). However, you definitely don't want to add view model information to your data models. Here's how I might do it (using your click-toggles-something-special example).

<div ng-repeat-start="thing in things">
    <div ng-if="$first || isSpecial" ng-include="/specialtemplate.html" ng-click="isSpecial = !isSpecial"></div>
    <div ng-if="!$first && !isSpecial" ng-include="/regulartemplate.html" ng-click="isSpecial = !isSpecial"></div>
</div>
<div ng-repeat-end></div>

The key difference is I'm adding the isSpecial property to the scope, not to thing, and isSpecial will be specific to that particular ng-repeat item's scope.

Also, unless you're planning on doing DOM manipulation, you can replace them with ng-include + ng-controller in the template html.

Some people prefer that pattern (include + controller) instead of directives, and other prefer to go ahead and others prefer to go ahead and write directives because it's more "componenty" (I made that word up). I think either is a valid way to go.

Joe Enzminger
  • 11,110
  • 3
  • 50
  • 75