How do I infer or close tag in ember handlebars if block?

I'm trying to use the Zurb Foundation grid in ember and I can't figure out how to get my template to correctly insert the start and end tags of a multi-column row.

I have a controller that spits out "isFirstOfRow, isLastOfRow" correctly, but I can't figure out how to get the Ember version of the rudders to spit out unbalanced open / close labels. My logic will balance them, but they will not balance in every iteration of the block {{#each}}

.

My template looks like this:

{{#each item in items}}
    These are all working perfectly, thanks to my mad math skills:
    {{item.firstOfRow}}
    {{item.lastOfRow}}

    The problems start here:
    {{#if item.firstOfRow}}
        <ul class="small-block-grid-1 medium-block-grid-2 large-block-grid-4">
            I shouldn't be closed immediately
    {{/if}}

    <li>
        <a href="/items/{{unbound id}}">
          <h4>{{item.title}}</h4>
          <p>{{item.description}}</p>
        </a>
    </li>

    ...and continue here:
    {{#if item.lastOfRow}}
            I should have been closed here.
            Ember outputs an unbalanced closing tag correctly,
            it the opening that has the problem!
        </ul>
    {{/if}}

{{else}}

    This is irrelevant, and is working perfectly...
    <ul><div class="text-center"><strong>No items found</strong></div></ul>

{{/each}}

      

It immediately closes the tag <ul>

at the top.

Is there a way to make the ember template render HTML but treat it recklessly as if it were plain text?

Edit: Following the comments / replies I received, here's a planned expansion of the template after all the magic has taken place. This is dictated by how grids usually work (and how Zurb works in particular). Classes are approximations, the element hierarchy is the important part:

<div class="table">
  <ul class="row">
    <li class="item">
      <a href="/items/item1573">
        <h4>First item</h4>
        <p>It an item!</p>
      </a>
    </li>
    <li class="item">
      <a href="/items/item4953">
        <h4>Second item</h4>
        <p>It another item!</p>
      </a>
    </li>
  </ul>
  <ul class="row">
    <li class="item">
      <a href="/items/item4333">
        <h4>Third item</h4>
        <p>Item item item</p>
      </a>
    </li>
    <li class="item">
      <a href="/items/item53213">
        <h4>Fourth item</h4>
        <p>Items galore</p>
      </a>
    </li>
  </ul>
</div>

      

And here is the controller code I am using to manipulate the template. It displays its properties perfectly. I'm just showing this to demonstrate the complete end-to-end solution I'm trying to do if you have a better suggestion for the intended markup:

ItemsController = Ember.ArrayController.extend
    itemController: 'item'
    items: (->
        length = @get 'length'
        @map (item, i) ->
            item.last = i + 1 == length
            item.first = i == 0
            item.firstOfRow = i % 2 == 0
            item.lastOfRow = (i + 1) % 2 == 0
            item
    ).property 'content.@each'

      

+3


source to share


2 answers


I don't believe there is a way to display unbalanced HTML tags inside the helper if

. But, if I understand what you are trying to do, you are working too hard. :)

Why not just wrap the whole thing inside a helper if/else

and display the items if the array is not empty (if the condition is true) and display a message if the array is empty? An empty array will evaluate to false

.

    {{#if items}}
      <ul>
        {{#each item in model}}
        <li>{{item}}</li>
        {{/each}}
      </ul>
    {{ else }}
      No items
    {{/if}}

      

See a working example here



UPDATE

You can also have nested each

with if

, for example:

  {{#each row in model}}
    {{#if row.items }}
      <ul>
        {{#each item in row.items }}
          <li>{{item}}</li>
        {{/each}}
      </ul>
    {{/if}}
  {{/each}}

      

See a working example here

+3


source


This may be necessary if you are using a regular grid (for example, if you have uneven columns or interesting row styles and sizes), but it is absolutely unnecessary if you are using a block grid.

See this fiddle: http://codepen.io/anon/pen/PwWRWa

If you are using block grid, just do a plain old one {{#each ...}}

with a vanilla array controller and you go gold!


I solved it by changing the way I output data from my controller, ala Kalman's suggestion .

Basic controller code:



`import Ember from "ember";`

GridController = Ember.ArrayController.extend
    rows: (->
        width = @get 'rowWidth'
        height = @get('length') / @get('rowWidth')
        result = Ember.A(Ember.A() for i in [0..height])
        @forEach (item, index) ->
            result[Math.floor(index / width)].push(item)
        return result
    ).property 'content.@each'

`export default GridController;`

      

Controller specific code (repeat as many grids as you need):

`import GridController from "./grid";`

BlahDeeBlahsController = GridController.extend
    itemController: 'blah-dee-blah'
    rowWidth: 4

`export default BlahDeeBlahsController;`

      

Template code:

{{#each row in rows}}
<ul class="small-block-grid-1 medium-block-grid-2 large-block-grid-4">
    {{#each item in row}}
    <li>
        <a href="/items/{{unbound id}}">
            <div class="panel text-center">
                <h4>{{item.title}}</h4>
                <p>{{item.description}}</p>
            </div>
        </a>
    </li>
    {{/each}}
</ul>
{{else}}
<ul><div class="text-center"><strong>No items found</strong></div></ul>
{{/each}}

      

I still think there might be a cleaner / more magical way to generate controller code than what I ran into, but that seems to solve the problem.

+2


source







All Articles