ActiveCampaign / mustachio

Lightweight, powerful, flavorful, template engine.
MIT License
207 stars 17 forks source link

How do you render when the variable could be an single object or an array of objects? #11

Open justshrey opened 6 years ago

justshrey commented 6 years ago

Hi,

Here is the issue i am having. Lets say we have an API return a data object which could be either this

{
    to : {  name : 'John'  }
}

or this

{
    to : [ 
             {  name : 'John'  },
             {  name : 'Jenny'  },
             {  name : 'Markl'  }
          ]
}

How do i render this on a template? If i use something like this.

To:  {{#each to}} {{name}} , {{/each}}

I get the error,

'to' is used like an array by the template, but is a scalar value or object in your model.

What am i missing? Couldn't really find this in the documentation

justshrey commented 6 years ago

Ok, have created a fix which essentially extends each syntax to accept the scenario above.

Let me know what you guys think?

soreng commented 6 years ago

@justshrey so in affect, you want to change the behaviour of "each", because your own code switches between types?

You should edit your model to always pass an array - even if there is only a single item

justshrey commented 6 years ago

@soreng yes. The point is that is not necessarily about my code. Its about the data which i get from an endpoint which i would prefer not to encapsulate.

What i am trying to understand is what exactly is the benefit of throwing an error?

In a lot of use cases there a distinct advantage in treating a scalar value as a single item in an array since we have explicitly stated the intent to handle one or many by the use of each within the template. It eliminates the need for conditionals in a template and avoid un-necessary encapsulation of any JSON that comes in.

soreng commented 6 years ago

What i am trying to understand is what exactly is the benefit of throwing an error? it is to tell you that you are trying to iterate a list, but providing a scalar value

I really don't see a problem in this, since this is how "each" works in every language. It would not be very intuitive to change that behaviour.

I have worked with a api that switched types, and it took forever to figure out a solution. All the serialization code had to have two input / output types, and then manually convert to a list with a single element.

justshrey commented 6 years ago

@soreng . Hmm ok.

I understand when it comes to any programming language having an array is expected behavior. However, this is supposed to be a logic-less templating system, ergo the comparisons would not be the same..

Having the each autobox a single scalar value to an array, would in this case be expected behaviour from the perspective on an end user. For that matter, if you look at the original mustache demo, http://mustache.github.io/#demo .

If we change the default data to this

{
  "header": "Colors",
  "items": {"name": "red", "first": true, "url": "#Red"},     
  "empty": false
}

i.e setting the items property to an object instead of an array, it still renders correctly as expected.

I really think that this should be added to the library since it help it become more congruent to the expected mustache template behaviour.

In case i am missing the point, could you help me understand this with an example where the boxing of a scalar value into a single item array would be an issue? Specifically, in this context i.e the logic-less template system.