Meteor-handlebar-helpers icon indicating copy to clipboard operation
Meteor-handlebar-helpers copied to clipboard

$mapped doesn't work with arrays of non-objects

Open epaminond opened this issue 10 years ago • 6 comments

For example $last helper never gets true value.

epaminond avatar Jan 18 '15 09:01 epaminond

Yes, because current implementation of $mapped has nothing to do with non-object values and tries to extend primitives.

evenfrost avatar Apr 07 '15 12:04 evenfrost

I saw that. Is it done for some reason or can this be changed?

epaminond avatar Apr 07 '15 12:04 epaminond

I believe this is implementation issue. There are some other issues that don't work for me, so I've created a package for similar purpose, gonna try to keep it updated.

evenfrost avatar Apr 07 '15 15:04 evenfrost

I do actually take pull requests :)

raix avatar Apr 07 '15 15:04 raix

Hey @raix, here's a first draft.

Template.registerHelper('$mapped', function(arr) {

  return _.map(arr, function(item, index) {
    /* jshint -W053 */
    // In this case we explicitly want String to be used as a constructor, so that we can add properties to it.
    var strObj = new String(item + 'abc');
    /* jshint +W053 */
    strObj.$first = index === 0;
    strObj.$index = index;
    strObj.$last = index === arr.length-1;
    return strObj;
  });
});

The only caveat is that in the template, instead of {{ this }} returning a raw string, it returns a String object which is then automatically cast to its String value. So, if a developer passes 'this' in the template context to some other function, it will be different than usually expected.

You could add a variable 'thisRaw' on strObj to allow the caller access to the raw string, which works but adds a slight cognitive load to anyone who uses $mapped.

The jshint directive is necessary because it's generally not ok to use new for a primitive constructor, but in this case we need to build an actual object.

A maybe-cleaner way to do this would be to inject variables into the data context, but core devs have said that that's an antipattern for various reasons, e.g. see #4: https://github.com/meteor/meteor/issues/1595#issuecomment-28338105.

One last thing, the current function assumes a string array, you'd have to wrap it in code that only executes once there actually IS a string array present.

LMK what you think.

vaughnkoch avatar May 26 '15 04:05 vaughnkoch

maybe just return an object with a toString?

raix avatar May 27 '15 12:05 raix