jehugaleahsa / mustache-sharp

An extension of the mustache text template engine for .NET.
The Unlicense
306 stars 78 forks source link

Greater Than / Equals / Less Than #17

Closed PaulGrimshaw closed 10 years ago

PaulGrimshaw commented 10 years ago

Any thoughts on how this might be implemented? There is a handlebars extension library which does this:

https://github.com/danharper/Handlebars-Helpers

It would be great to enable multiple level lists, for example:

{{#each Category}}
<h1>{{Name}} - {{MainCategoryId}}</h1>
{{#each Product}}
{{#is CategoryId MainCategoryId}}
<h4>{{ProductName}}</h4>
{{/is}}

Or for conditional formatting:

{{#each Budget}}
<h3 
{{#is amount ">=" 200}}class="overbudget"{{/is}}
>{{Name}}</h3>
jehugaleahsa commented 10 years ago

Unfortunately, the library doesn't accept string or numeric constants. In the future, perhaps someone with a little more programming language theory under their belt can help out. Right now, I have a recursive descent parser doing all the work. If you take a look at the code base, the parsing and the processing are clumped together. It will be difficult to extend the language until I can separate those responsibilities.

In the meantime, the trick is to add to your model, generating properties for each of these comparisons. For instance, adding properties IsMainCategory and IsOverBudget.

PaulGrimshaw commented 10 years ago

Could this not work using a variation of your "Set" tag? Or by using a special character to parse the string/numeric value, such as {{#is amount #gt @200}} or so? Take your point about extending the model, but what i like about this library is it negates the need to form ViewModels etc...

Alternatively, would it be possible to build something with custom tags, using reflection to get the variable names? http://stackoverflow.com/questions/9801624/get-name-of-a-variable-or-parameter gets me thinking...

Any guidance would be much appreciated... afraid I don't have the know how or guts to dive in and change your code (yet!).

jehugaleahsa commented 10 years ago

I could see a tag called #gt that took two variables: {{#gt amount @max}}. Such a tag wouldn't be that hard to create. You could look at the code for ConditionalTagDefinition and just override the ShouldGeneratePrimaryGroup method. On Feb 3, 2014 7:15 PM, "Paul Grimshaw" notifications@github.com wrote:

Could this not work using a variation of your "Set" tag? Or by using a special character to parse the string/numeric value, such as {{#is amount

gt @200 https://github.com/200}} or so? Take your point about

extending the model, but what i like about this library is it negates the need to form ViewModels etc...

Alternatively, would it be possible to build something with custom tags, using reflection to get the variable names?

Any guidance would be much appreciated... afraid I don't have the know how or guts to dive in and change your code (yet!).

Reply to this email directly or view it on GitHubhttps://github.com/jehugaleahsa/mustache-sharp/issues/17#issuecomment-34017196 .

PaulGrimshaw commented 10 years ago

This is great, got me well along the way and have successfullly made an {{#eq OneValue AnotherValue}} tag. Will complete the set with {{#gt OneValue AnotherValue}}, {{#gte...}}, {{#ls...}}, {{#lse}}. Will build in "{{#else}}" for all of them too.

Forked onto my GitHub profile, feel free to bring changes back in if you feel they'll be useful.

PaulGrimshaw commented 10 years ago

So now with that all running, could you give me any pointer as to how i might get a value straight from the template into a tag, without first feeding it into the model?

var model = new {Amount = 30, Limit = 31};
var format = {{#gt Amount Limit}}Over Limit!{{/gt}}

The above is working great. However I'd really like my users to be able to enter the limit into the template somehow...

 var model = new {Amount = 30};
 var format = {{#gt Amount 31}}Over Limit!{{/gt}}

or

 var model = new {Amount = 30};
 var format = {{#gt Amount @31}}Over Limit!{{/gt}}

or

 var model = new {Amount = 30};
 var format = {{#gt Amount ?31}}Over Limit!{{/gt}}

Any possible direction pointers?

PaulGrimshaw commented 10 years ago

Ok, I've made this work in the following manner, and any value, string or number can be written directly into the placeholder by prefixing with "_" (any idea of a better symbol are welcome, as the ideal one "@" is taken...)

Examples:

 var model = new {Amount = 30};
 var format = "{{#gt Amount _31}}Over Limit!{{/gt}}"

 var model = new {ViewId = "vid876"};
 var format = "<a class="{{#eq ViewId _vid876}}active{{/gt}}">home page</a>"

All available here https://github.com/PaulGrimshaw/mustache-sharp

FYI I did this simply by adding two lines to the "ArgumentCollectionCode.cs", in the "GetArguments(...)" method:

....
            if (pair.Value == null)
            {
                value = pair.Key.DefaultValue;
            }
            else if (pair.Value.StartsWith("@"))
            {
                value = contextScope.Find(pair.Value.Substring(1));
            }
            //ADDED THIS:
            else if (pair.Value.StartsWith("_")) {
                value = pair.Value.Remove(0, 1);
            }
            //END OF ADDITION
            else
            {
                value = keyScope.Find(pair.Value);
            }
            arguments.Add(pair.Key.Name, value);
        }
        return arguments;
....