Insert can.compute into can.Map #1409

Closed
Aldredcz opened this Issue Jan 20, 2015 · 6 comments

Comments

Projects
None yet
4 participants
@Aldredcz

Hello,

One feature I would really appreciate - insert can.compute (the value one, not the function one) into can.Map, so I can use it with normal can.Map interface and having all bindings working on 'both sides', as it works when inserting can.Map into other can.Map, example:

var slaveMap = new can.Map({foo: 1});
var masterMap = new can.Map(innerMap: slaveMap);

// then this works
masterMap.innerMap.attr('foo', 5);
slaveMap.attr('foo') === 5; // true


var compute = can.compute(1);
var map = new can.Map(insertedCompute: compute);

// how it works
map.insertedCompute(); // yields 1
map.insertedCompute(5); // sets 5

// how it would be awesome
map.attr('insertedCompute') // yields 1
map.attr('insertedCompute', 5) // sets 5

What is the main goal? To get this pattern working:

var map1 = new can.Map({a: 1, b: 2});
var map2 = new can.Map({c: 3, d: 4});

var map3 = new can.Map({
    a: map1.compute('a'),
    c: map2.compute('c')
});

Since Components are based on data coupling it would be extremely useful to have this possibility.

Unfortunately, there would be problem with backward compatibility, since someone could use it nowadays with current functionality, but it could be done by defining method like:

var compute = can.compute(1);
var map = new can.Map({});

map.insertCompute('nameOfAttr', compute);
@justinbmeyer

This comment has been minimized.

Show comment
Hide comment
@justinbmeyer

justinbmeyer Jan 21, 2015

Contributor

Thanks for submitting this.

I think this might be possible currently with the define plugin. I don't think we can support it natively. I'm not a fan of calling it insertCompute.

It seems you are just wanting to 2-way bind a compute to a map. I'm not sure why this would help components as they already make this happen.

Sent from my iPhone

On Jan 20, 2015, at 5:46 PM, Aldredcz notifications@github.com wrote:

Hello,

One feature I would really appreciate - insert can.compute (the value one, not the function one) into can.Map, so I can use it with normal can.Map interface and having all bindings working on 'both sides', as it works when inserting can.Map into other can.Map, example:

var slaveMap = new can.Map({foo: 1});
var masterMap = new can.Map(innerMap: slaveMap);

// then this works
masterMap.innerMap.attr('foo', 5);
slaveMap.attr('foo') === 5; // true

var compute = can.compute(1);
var map = new can.Map(insertedCompute: compute);

// how it works
map.insertedCompute(); // yields 1
map.insertedCompute(5); // sets 5

// how it would be awesome
map.attr('insertedCompute') // yields 1
map.attr('insertedCompute', 5) // sets 5
What is the main goal? To get this pattern working:

var map1 = new can.Map({a: 1, b: 2});
var map2 = new can.Map({c: 3, d: 4});

var map3 = new can.Map({
a: map1.compute('a'),
c: map2.compute('c')
});
Since Components are based on data coupling it would be extremely useful to have this possibility.

Unfortunately, there would be problem with backward compatibility, since someone could use it nowadays with current functionality, but it could be done by defining method like:

var compute = can.compute(1);
var map = new can.Map({});

map.insertCompute('nameOfAttr', compute);

Reply to this email directly or view it on GitHub.

Contributor

justinbmeyer commented Jan 21, 2015

Thanks for submitting this.

I think this might be possible currently with the define plugin. I don't think we can support it natively. I'm not a fan of calling it insertCompute.

It seems you are just wanting to 2-way bind a compute to a map. I'm not sure why this would help components as they already make this happen.

Sent from my iPhone

On Jan 20, 2015, at 5:46 PM, Aldredcz notifications@github.com wrote:

Hello,

One feature I would really appreciate - insert can.compute (the value one, not the function one) into can.Map, so I can use it with normal can.Map interface and having all bindings working on 'both sides', as it works when inserting can.Map into other can.Map, example:

var slaveMap = new can.Map({foo: 1});
var masterMap = new can.Map(innerMap: slaveMap);

// then this works
masterMap.innerMap.attr('foo', 5);
slaveMap.attr('foo') === 5; // true

var compute = can.compute(1);
var map = new can.Map(insertedCompute: compute);

// how it works
map.insertedCompute(); // yields 1
map.insertedCompute(5); // sets 5

// how it would be awesome
map.attr('insertedCompute') // yields 1
map.attr('insertedCompute', 5) // sets 5
What is the main goal? To get this pattern working:

var map1 = new can.Map({a: 1, b: 2});
var map2 = new can.Map({c: 3, d: 4});

var map3 = new can.Map({
a: map1.compute('a'),
c: map2.compute('c')
});
Since Components are based on data coupling it would be extremely useful to have this possibility.

Unfortunately, there would be problem with backward compatibility, since someone could use it nowadays with current functionality, but it could be done by defining method like:

var compute = can.compute(1);
var map = new can.Map({});

map.insertCompute('nameOfAttr', compute);

Reply to this email directly or view it on GitHub.

@justinbmeyer

This comment has been minimized.

Show comment
Hide comment
@justinbmeyer

justinbmeyer Jan 21, 2015

Contributor

With the define plugin:

var MyMap = can.Map.extend({
  define: {
    nameOfAttr: {
      get: function(val){
        return val || val()
      }
    }
  }
});

new MyMap({ nameOfAttr: can.compute(5) })
Contributor

justinbmeyer commented Jan 21, 2015

With the define plugin:

var MyMap = can.Map.extend({
  define: {
    nameOfAttr: {
      get: function(val){
        return val || val()
      }
    }
  }
});

new MyMap({ nameOfAttr: can.compute(5) })
@Aldredcz

This comment has been minimized.

Show comment
Hide comment
@Aldredcz

Aldredcz Feb 1, 2015

Not sure, the define 'hack' is the case i want achieve.

The case with Components:

Imagine, you have a Component used by many types of parent Components (lets call it Widget). This Component accepts 3 parameters and modifies them. Since you can't pass computes directly into Component, you probably pass can.Map like:

can.Map({
    param1: value,
    param2: value,
    param3: value
});

One Widget has all these parameters in one object, so you can just pass it as it is.

var stuff = new can.Map({
    // many params here including our 3
    param1: value,
    param2: value,
    param3: value
    // and many many more
})

But another Widget using the same Component could have these parameters spread over many different objects.

In this situation, this would be really good solution:

var params = new can.Map({
    param1: obj1.compute('param1'),
    param2: obj2.compute('param2'),
    param3: obj3.compute('notEvenNamedParam3')
});

And any change made would also be propagated to the original obj1/obj2/obj3 can.Map.

About syntax, one more idea, what about extending can.compute prototype with a method, which would produce same compute, but when passing to can.Map, it would have described functionality?

var params = new can.Map({
    param1: obj1.compute('param1').methodName() // e.g. insertable?
});

Aldredcz commented Feb 1, 2015

Not sure, the define 'hack' is the case i want achieve.

The case with Components:

Imagine, you have a Component used by many types of parent Components (lets call it Widget). This Component accepts 3 parameters and modifies them. Since you can't pass computes directly into Component, you probably pass can.Map like:

can.Map({
    param1: value,
    param2: value,
    param3: value
});

One Widget has all these parameters in one object, so you can just pass it as it is.

var stuff = new can.Map({
    // many params here including our 3
    param1: value,
    param2: value,
    param3: value
    // and many many more
})

But another Widget using the same Component could have these parameters spread over many different objects.

In this situation, this would be really good solution:

var params = new can.Map({
    param1: obj1.compute('param1'),
    param2: obj2.compute('param2'),
    param3: obj3.compute('notEvenNamedParam3')
});

And any change made would also be propagated to the original obj1/obj2/obj3 can.Map.

About syntax, one more idea, what about extending can.compute prototype with a method, which would produce same compute, but when passing to can.Map, it would have described functionality?

var params = new can.Map({
    param1: obj1.compute('param1').methodName() // e.g. insertable?
});
@justinbmeyer

This comment has been minimized.

Show comment
Hide comment
@justinbmeyer

justinbmeyer Feb 1, 2015

Contributor

Sorry, I'm not sure what you are saying. It's confusing because it's abstract, and you're showing map code, not components and views that assemble the behavior you are looking for.

I'm not sure what you mean by "you probably pass can.Map". You normally pass each "param" individually as an attribute on the component. Ex <my-widget param1="{parent1Key}" ....>.

But another Widget using the same Component could have these parameters spread over many different objects.

Yep, but it could pass them accordingly: <my-widget param1="{parent2.someObj.key}" ....>.

Hit me up on gitter Monday.

Sent from my iPhone

On Jan 31, 2015, at 6:23 PM, Aldredcz notifications@github.com wrote:

Not sure, the define 'hack' is the case i want achieve.

The case with Components:

Imagine, you have a Component used by many types of parent Components (lets call it Widget). This Component accepts 3 parameters and modifies them. Since you can't pass computes directly into Component, you probably pass can.Map like:

can.Map({
param1: value,
param2: value,
param3: value
});
One Widget has all these parameters in one object, so you can just pass it as it is.

var stuff = new can.Map({
// many params here including our 3
param1: value,
param2: value,
param3: value
// and many many more
})
But another Widget using the same Component could have these parameters spread over many different objects.

In this situation, this would be really good solution:

var params = new can.Map({
param1: obj1.compute('param1'),
param2: obj2.compute('param2'),
param3: obj3.compute('notEvenNamedParam3')
});
And any change made would also be propagated to the original obj1/obj2/obj3 can.Map.

About syntax, one more idea, what about extending can.compute prototype with a method, which would produce same compute, but when passing to can.Map, it would have described functionality?

var params = new can.Map({
param1: obj1.compute('param1').methodName() // e.g. insertable?
});

Reply to this email directly or view it on GitHub.

Contributor

justinbmeyer commented Feb 1, 2015

Sorry, I'm not sure what you are saying. It's confusing because it's abstract, and you're showing map code, not components and views that assemble the behavior you are looking for.

I'm not sure what you mean by "you probably pass can.Map". You normally pass each "param" individually as an attribute on the component. Ex <my-widget param1="{parent1Key}" ....>.

But another Widget using the same Component could have these parameters spread over many different objects.

Yep, but it could pass them accordingly: <my-widget param1="{parent2.someObj.key}" ....>.

Hit me up on gitter Monday.

Sent from my iPhone

On Jan 31, 2015, at 6:23 PM, Aldredcz notifications@github.com wrote:

Not sure, the define 'hack' is the case i want achieve.

The case with Components:

Imagine, you have a Component used by many types of parent Components (lets call it Widget). This Component accepts 3 parameters and modifies them. Since you can't pass computes directly into Component, you probably pass can.Map like:

can.Map({
param1: value,
param2: value,
param3: value
});
One Widget has all these parameters in one object, so you can just pass it as it is.

var stuff = new can.Map({
// many params here including our 3
param1: value,
param2: value,
param3: value
// and many many more
})
But another Widget using the same Component could have these parameters spread over many different objects.

In this situation, this would be really good solution:

var params = new can.Map({
param1: obj1.compute('param1'),
param2: obj2.compute('param2'),
param3: obj3.compute('notEvenNamedParam3')
});
And any change made would also be propagated to the original obj1/obj2/obj3 can.Map.

About syntax, one more idea, what about extending can.compute prototype with a method, which would produce same compute, but when passing to can.Map, it would have described functionality?

var params = new can.Map({
param1: obj1.compute('param1').methodName() // e.g. insertable?
});

Reply to this email directly or view it on GitHub.

@justinbmeyer

This comment has been minimized.

Show comment
Hide comment
@justinbmeyer

justinbmeyer Feb 11, 2015

Contributor

@Aldredcz Any more thoughts on this? By gitter, I meant: https://gitter.im/bitovi/canjs . Thanks!

Contributor

justinbmeyer commented Feb 11, 2015

@Aldredcz Any more thoughts on this? By gitter, I meant: https://gitter.im/bitovi/canjs . Thanks!

@akagomez akagomez added this to the 2.2.0 milestone Feb 25, 2015

@akagomez akagomez self-assigned this Feb 25, 2015

akagomez pushed a commit that referenced this issue Feb 25, 2015

akagomez pushed a commit to akagomez/canjs that referenced this issue Feb 25, 2015

akagomez pushed a commit to akagomez/canjs that referenced this issue Feb 27, 2015

akagomez pushed a commit to akagomez/canjs that referenced this issue Feb 27, 2015

justinbmeyer added a commit that referenced this issue Mar 1, 2015

@justinbmeyer justinbmeyer assigned justinbmeyer and unassigned akagomez Mar 2, 2015

justinbmeyer added a commit that referenced this issue Mar 3, 2015

@daffl

This comment has been minimized.

Show comment
Hide comment
@daffl

daffl Mar 3, 2015

Contributor

This should be fixed now via #1486 (as mentioned in #1470)

Contributor

daffl commented Mar 3, 2015

This should be fixed now via #1486 (as mentioned in #1470)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment