How to get only true keys from reactiveDict?

I have a reactiveDict with these keys

>t.selectedParcelIds.keys
>Object {PP-dev-9dCpuC: "true", PP-dev-xp2wkq: "false", PP-dev-gHct57: "true"}

I’m trying to get just the keys which are true, to pass to another template. But since they keys are not strings, it seems underscore chokes on it. How to deal with this? I can’t even create a fiddle because it’s not valid JSON.

var keysObj  = t.selectedParceIds.keys:
var keys = Object.keys(keysObj);
var trueKeys = keys.reduce(function(result, key){
  if (keysObj[key]){
    result.push(key);
  }
  return result;
  },[]};

Thanks! I’ll try it tomorrow (3AM here in Japan now).

Complicated isn’t it? Sometimes I miss .NET development . . .

Cheers!

With actual underscore from npm, you could it much simpler :

var keysObj  = t.selectedParceIds.keys;
var trueKeys = _.pick(keysObj, function(value, key){
  return value;
});

However with underscore included with Meteor, this doesn’t work :frowning:

Other way to do that imperatively :

var keysObj  = t.selectedParceIds.keys;
var trueKeys = [];
Object.keys(keysObj).forEach(function(key){
  if (keysObj[key]){
    trueKeys.push(key);
  }
};

Another :

var keysObj  = t.selectedParceIds.keys;
var trueKeys = _.map(keysObj, function(value, key){
  return keysObj[key] && key;
};
trueKeys = _.compact(trueKeys); //to remove falsy values

JS is fun :smile:

can you help me understand the nature of the keys? So it seems like it’s not a normal JSON doc. I can’t do this for example:

var keysObj = {PP-dev-9dCpuC: "true", PP-dev-xp2wkq: "false", PP-dev-gHct57: "true"};

It’s some kind of special object? Is there no JSON for it?

How, for example, could I run your sample code in JSFIDDLE? I’d need to initialize some keys obj variable because t.selectedParcelIds.keys isn’t available, but I’m not sure how to do that.

Is there some special JavaScripts docs I should read? I don’t remember Object.keys from the books I read.

This one doesn’t actually work. False keys are still included in the final trueKeys result.

This can’t work because keys is a function :wink:

also unexpected token } at the end.

var keysObj  = t.selectedParceIds.keys:
var keys = Object.keys(keysObj);
var trueKeys = keys.reduce(function(result, key){
  if (keysObj[key]){
    result.push(key);
  }
  return result;
  },[]};

This one didn’t work either (imperatively). I added the missing “)” at the end, but the final trueKeys result include both true and false keys.

This keys things doesn’t seem to work as expected does it!

OK I got it working by changing the if statement

Object.keys(keysObj).forEach(function(key){
  if (keysObj[key] === "true"){
    trueKeys.push(key);
  }
});

Odd that true is a string, but that’s how it seems to work! When you set a ReactiveDict it converts true/false into strings
this.selectedParcelIds.set(this.parcel._id, false);

OK got this working too, after this change

var trueKeys = _.map(keysObj, function(value, key){
  if (value === "true") {return key};
});

The conclusion is that you shouldn’t acess a reactive-dict values through the reactive-dict.keys property.

Instead get the keys like this

var keys = Object.keys(t.selectedParceIds.keys);

an then check the values like this :

var trueKeys = [];
keys.forEach(function(key){
  if (t.selectedParceIds.get(key)){
    trueKeys.push(key);
  }
});

Again not tested, but it should work.

We learn something everyday :smile:

1 Like

but this actually works,


var selectedParcels = _.map(t.selectedParcelIds.keys, function(value, key) {
  if (value === "true") {
    return _.findWhere(currentData.packages, {_id: key});
  }
});
selectedParcels = _.compact(selectedParcels); // removed undefined values

Yes probably, but this is a hack, you are working with the inner parts of reactive-dict.
What if instead of a stroolean (string as a boolean :wink:), you want to test for a “strumber” ? You will have to remember to manually cast ?

reactive-dict.keys is a mix between a string key and a json string representation of the value, but doesn’t seem to be a valid JSON object which you could parse.
IMHO, it should have been _keys or whatsoever, and there should be public, documented, getKeys() which should retrieve an array of key names instead of this hybrid structure.
Time for a PR, i guess…

I think part of the thinking is that they can’t have vars in a reactiveDict which are objects (yet), so they are trying to prevent you from adding an object (i.e. stringify the values)

https://gist.github.com/chicagogrooves/0d062c061bbf87238f75#file-meteor-deps-dict-L434-L442

instead of get() and set() perhaps add() and remove() would have been a better way to go. Along with clear() and item() and containsKey . . . basically how it’s done in .NET :wink: But guess we have to work with what we got.

someone at least thought about it
https://gist.github.com/chicagogrooves/0d062c061bbf87238f75#file-meteor-deps-dict-L417

Here you can see why this doesn’t work. keys gets the keys but not any values!

This is what intended, getting the keys and not the values since those “jsonized” values are useless.
It don’t see why my last published code would not work (not tested though).

1 Like