-1

I'm trying to do something pretty simple: I'd like to show the NBA teams by conference, but that isn't the structure of the JSON.

I don't want to ask for a REST service structure change, i.e., make teams a child array of conference node.

This is a presentation issue, i.e., the JSON has the data I need, but how can I present it using dustjs?

You can see my jsfiddle attempt here: xpath equivalent jsdust

<script id="league-template2">
    <div class="conference"> 
    <h3>[I WANT TO PUT THE CONFERENCE NAME HERE EG EASTERN] Conference</h3>
    {#teams}   
        <ul>
            {#properties}            
                {@eq key=name value="numeric"}
                    <li class="teamName teamdd_{value}">
                        <div class="logo-nba-small nba-small-[I WANT TO PUT THE ABBV HERE EG PHI]"><a>[I WANT TO PUT TEAM NAME HERE EG 76ERS]</a></div>
                    </li>
                {/eq}
            {/properties}
        </ul>
   {/teams}
   </div>
</script>
<div id="output3"></div><br />


    $(document).ready(function() {
    var league2014 = {
    "teams": [{
        "properties": [{
        "years": null,
        "name": "conference",
        "value": "eastern"
        }, {
        "years": null,
        "name": "abbv",
        "value": "phi"
        }, {
        "years": null,
        "name": "numeric",
        "value": "20"
        }],
        "name": "76ers"
    }, {
        "properties": [{
        "years": null,
        "name": "conference",
        "value": "western"
        }, {
        "years": null,
        "name": "abbv",
        "value": "mem"
        }, {
        "years": null,
        "name": "numeric",
        "value": "29"
        }],
        "name": "grizzlies"
    }, {
        "properties": [{
        "years": null,
        "name": "conference",
        "value": "eastern"
        }, {
        "years": null,
        "name": "abbv",
        "value": "was"
        }, {
        "years": null,
        "name": "numeric",
        "value": "27"
        }],
        "name": "wizards"
    }]
    }    
    var source3 = $("#league-template2").html();
    var compiled3 = dust.compile(source3, "intro3");
    dust.loadSource(compiled3);
    dust.render("intro3", league2014, function(err, out) {
    $("#output3").html(out);
    });
});
Tom McDonald
  • 1,532
  • 2
  • 18
  • 37

2 Answers2

0

Try this:

<div class="conference"> 
{#teams}
  {#properties teamName=name}
    {@select key=name}
      {@eq value="conference"}
        <h3>{value} Conference</h3><ul>
      {/eq}
      {@eq value="numeric"}
        <li class="teamName teamdd_{value}">
      {/eq}
      {@eq value="abbv"}
        <div class="logo-nba-small nba-small-{value}"><a>{teamName}</a></div>
        </li>
      {/eq}
    {/select}
  {/properties}
  </ul>
{/teams}
</div>
myusuf
  • 11,810
  • 11
  • 35
  • 50
  • Thanks. That gets me part of the way: It now looks like this: [code] eastern Conference 76ers western Conference grizzlies eastern Conference wizards You can see the jsfiddle here [link](http://jsfiddle.net/bodyrock/3qLb2ge9/1/) – Tom McDonald Dec 07 '14 at 14:58
  • I should say what I'm after is to have the teams grouped under their conference name. So in the example it would have EASTERN 76ers wizards WESTERN grizzlies. – Tom McDonald Dec 07 '14 at 15:07
  • For that, I'd recommend restructuring your data. Trying to implement with the current data would result in a highly inefficient dust-template. – myusuf Dec 07 '14 at 15:40
  • Thanks, but the service team would laugh in my face if I told them to restructure the data to suit my presentation. They'd start reading from text books about why I shouldn't do that. – Tom McDonald Dec 07 '14 at 17:33
  • I mean, you can restructure it at your end. – myusuf Dec 07 '14 at 17:43
  • Right, but isn't that what Dust is supposed to do, i.e., change JSON TO HTML? How do you propose I restructure it? JSON to JSON to HTML? If so, that seems redundant. – Tom McDonald Dec 07 '14 at 22:19
  • Something's gotta give ;) Is the data always going to be like this? i.e. conference, followed by abbv and numeric ? If we can make that assumption, then we can have a non-generic but working solution. – myusuf Dec 08 '14 at 06:15
  • Correct, the REST service never changes. Once the REST Team defines it then that's it and I have to work with whatever it is. – Tom McDonald Dec 08 '14 at 16:23
  • I would take advantage of Dust's very-helpful ability to write functions and add them to your context. – Interrobang Dec 10 '14 at 05:01
  • lesson learned. 1. Dustjs forces the REST data hierarchy to conform, almost exactly, to the presentation hierarchy. 2. Given that, why would I ever use dustjs when there are more robust templating – Tom McDonald Dec 12 '14 at 19:34
  • Because the logic you're asking for (grouping) doesn't belong at the template layer. It belongs in a view model, which Dust supports through the use of context helpers. – Interrobang Dec 12 '14 at 19:39
  • For example, client side XSLT can work with any data structure and turn it into whatever I want. – Tom McDonald Dec 12 '14 at 19:41
0

Here's how I would do it to fit your requirements while keeping the template simple.

Template:

<div class="conference"> 
{#teamsByConference}
  <h3>{conference}</h3>
  <ul>
  {#teams}
    <li class="teamName teamdd_{numeric}">
      <div class="logo-nba-small nba-small-{abbv}"><a>{name}</a></div>
    </li>
  {/teams}
  </ul>
{/teamsByConference}
</div>

Context:

{
    // This is a Dust context function. It's called a handler!
    // It gets called by Dust when you try to access it. Handlers act like variables in templates
    // But they can do much more than just return a value. They can make async AJAX requests,
    // create new data, and all sorts of things. They're (in my opinion) one of the best features of Dust.
    // https://github.com/linkedin/dustjs/blob/master/docs/api.md#handlers
    "teamsByConference": function(chunk, context, bodies, params) {
      // Get the teams variable from the Dust context. You can use this.teams, but
      // that won't walk the context tree in case this function is at a different level
      var teams = context.get("teams"),
          conferences = {},
          conferenceList = [],
          conference,
          x;

      // I'm using ECMAScript 5 just to save space
      // Transform the JSON into the format we want and store it in conferences
      teams.forEach(function(team) {
        // Teams have an array of properties, but it'd be much more JSON-like if they
        // were keys in an Object. So I'll reduce the array to a single object.
        // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/Reduce
        var newTeam = team.properties.reduce(function(acc, prop) {
          acc[prop.name] = prop.value;
          return acc;
        }, {});
        newTeam.name = team.name;

        // Combine teams by their conference
        conferences[newTeam.conference] = conferences[newTeam.conference] || [];
        conferences[newTeam.conference].push(newTeam);
      });

      // Transform the conference object into an array so Dust iterates over it
      for(conference in conferences) {
        conferenceList.push({ conference: conference, teams: conferences[conference] });
      }

      // At this point we have an array of conferences. Each conference contains an array of teams!
      // Iterate over the returned list of conferences by returning it
      // Dust chunks and contexts are super-cool and you can read the source to learn all about them
      return conferenceList;
    },

    "teams": [...]
    } 

I'm using a context helper to format the data in your context the way that it should be. This keeps any grouping or membership logic out of your template.

If you don't like this philosophy, that's OK-- but this is Dust's philosophy.

Interrobang
  • 16,984
  • 3
  • 55
  • 63
  • Thanks, but I'm having difficulty reading your code. Can you point me to a site that can explain this technique? – Tom McDonald Dec 12 '14 at 21:30
  • I will add additional comments to the code. The only "magic" part is the `chunk.section` call. The rest is just `Array#reduce` and `Array#map`: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array – Interrobang Dec 12 '14 at 21:45
  • You called this a 'handler' in your comments. Did you mean to call this a dust 'helper'? I can't find 'handler' tutorials/examples. If you could provide a link to a JSFiddle example that would help me study this technique. – Tom McDonald Dec 15 '14 at 21:49
  • Helpers are standalone functions added to `dust.helpers`. Handlers are functions in your context. Other than that they are the same; they're both passed `chunk, context, bodies, params`. The first comment in the code contains a link to an explanation of handlers. – Interrobang Dec 15 '14 at 22:18
  • Yes, I appreciate your help, but it's too abstract. I need an example, tutorial, jsfiddles, etc. I'm unable to find these things in my google searches. – Tom McDonald Dec 17 '14 at 15:12
  • Is this a good example of the technique you are suggesting? http://jsfiddle.net/amiramix/Y2ztc/ – Tom McDonald Dec 18 '14 at 20:41
  • Interrobang, thanks but I'm a dust newbie. I've been researching this technique for hours and can't figure it out. It would be a huge help if you could fork my JSFiddle and show me how its done. http://jsfiddle.net/bodyrock/5nykr8wz/9/ – Tom McDonald Dec 18 '14 at 21:11
  • Looks like I'm on my own. Based upon what I'm reading at http://akdubya.github.io/dustjs/ it seems that in order to use Interobangs handler code (above) I have to merge it with the JSON response I get from the REST service...is that right? – Tom McDonald Dec 22 '14 at 16:52
  • I've written more about handlers on the official docs site: http://www.dustjs.com/guides/context-helpers/ – Interrobang Mar 17 '15 at 17:13