mikeric / rivets

Lightweight and powerful data binding.

Home Page:http://rivetsjs.com

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Rivets formatter when each argument is another formatter

opened this issue · comments

I want to check if table.value is equal to 'Stack' or 'Overflow'.

I would like to do something like this:

rv-if="table.value | eq 'Stack' | or (table.value | eq 'Overflow')"

rivets.formatters.eq = function (value, args)  { 
         return value === args;
};

rivets.formatters.or = function (value, args)  { 
         return value || args;
};

I would like to use those 2 formatters to achieve this.

I know I can have a specific formatter like this to achieve my functionality.

rivets.formatters.checkIfValueEqualsEitherArg = function (value, arg1, arg2)  { 
             return (value === arg1) || (value===arg2);
};

rv-if="table.value | checkIfValueEqualsEitherArg 'Stack' 'Overflow'"

But, I would rather use the above two generic formatters (eq and or).

What is the best way to achieve this

I have encountered same thing once. I have solved this by providing such anyOf formatter:

rivets.formatters.anyOf = (value, arrayAsStr) => {
	return NS.Array.indexOf(arrayAsStr.split(','), value, true) >= 0
}

Usage:

<div class="item-settings-row" rv-if="item.type | anyOf 'Shirt,Jacket,Hoodie'">
</div>

To me this one feels generic enough, it's readable and understandable.

Thanks for the response. It does look better than my solution. But, I would still like a generic way to have a formatter where it has multiple parameters that can be formatters.

RPN

What you want is probably a support for expressions - a hierarchical structure of nesting binary expressions. Formatters are linear, though. So there is no support for nesting. I tried to think of anything like this and it would be possible using https://en.wikipedia.org/wiki/Reverse_Polish_notation underneath. However, the syntax would be a little weird.

Formatter would need to pass some "builder" object instead of just a value. Next formatter would take it, check if it's just a value or instanceof the builder and continue adding to it. However, I'm not sure how to get information which formatter is the latest one. Maybe overriding toString() in prototype would help: https://stackoverflow.com/questions/6307514/is-it-possible-to-override-javascripts-tostring-function-to-provide-meaningfu

Full expressions

Other way is total overkill in terms of size (10 KB). You could take this parser for expressions (there are no statements, just expressions!) https://github.com/Namek/js_expr and implement it as formatter. Then, you could pass expression as text as a first argument and all values to expression as next arguments. Or, play a little more with getting values by names from rivets context but I'm not too experienced in that.

?

I don't see any other option than extending rivets itself. If you achieve anything interesting then please share with us :)

I agree that this is out of scope. You could very easily implement the expression parser as a formatter, as @Namek says. Implementing it in rivets core would increase the size of the package considerably. There could be some mileage with the use of parentheses, but I think it opens a can of worms – in your example, you used or (table.value | eq 'Overflow'), but what if you used or (a-totally-different-variable | eq 'Overflow')? The linear nature of formatters allows rivets to remain simple.

Also, there is no one currently able to spend a lot of time on rivets, so new functionality is not going to come from maintainers. I (I can only speak for myself really) am very happy to look at PRs if I have time, but my personal circumstances mean I don't get a lot of time to look at rivets, and no other maintainers with push access seem to have that time either.