Proposal: `can-scope` for exporting scope into the surrounding context. #1362

Closed
zkat opened this Issue Dec 8, 2014 · 4 comments

Comments

Projects
None yet
3 participants
@zkat
Contributor

zkat commented Dec 8, 2014

Proposal

As we start using components more, we will want to add methods to our components that are meant for external use. #881 was an attempt to address this issue, but in keeping with our policy of isolating the DOM and ViewModel layers, I think it's better to expect these methods to mainly be accessed through the component viewmodels.

To facilitate this, I think following something similar to what Polymer does, by providing a simple mechanism for giving easy accessible names to child scopes. These names would be accessible directly through the component templates, and further

I propose using a can-scope attribute for facilitating access to child component functionality in a template, and in the component's viewModel. I further propose that non-Component html tags that use the can-id attribute will automatically be treated as a can-value, and have that value be accessible instead.

Concretely, can-scope will export the tag's scope into a name in the surrounding template. The attribute will also automatically add can-value-like functionality if used on a non-component.

Justification and Notes

This may require #1069 for proper operation, and will be much improved by #1360. Having #1361 would also be much more valuable here, since we would be able to just directly pass arguments to child scope methods.

Examples

<gt-placement-request param-new-name="{nameInput.value}" can-scope="{allPlacementsReq}" can-request-done="{notifyDone allPlacementsReq.value}">
</gt-placement-request>
<bs-button can-click="{allPlacementsReq.go placement}">Submit</bs-button>
<input can-scope="{nameInput}">
{{#if allPlacementsReq.error}}
    There's an error! {{allPlacementsReq.error}}
{{/if}}
 // in JS, too
scope: {
  getPlacements: function() {
    return this.attr("allPlacementsReq").go();
  }
}

@zkat zkat changed the title from Proposal: $$ and `can-id`. to Proposal: `can-scope` for exporting scope into the surrounding space. Feb 16, 2015

@zkat zkat changed the title from Proposal: `can-scope` for exporting scope into the surrounding space. to Proposal: `can-scope` for exporting scope into the surrounding context. Feb 16, 2015

@daffl daffl added this to the 2.3.0 milestone Mar 5, 2015

@justinbmeyer

This comment has been minimized.

Show comment
Hide comment
@justinbmeyer

justinbmeyer May 6, 2015

Contributor

Regarding this, would

<gt-placement-request param-new-name="{nameInput.value}" this="{allPlacementsReq}" can-request-done="{notifyDone allPlacementsReq.value}">
</gt-placement-request>
<bs-button can-click="{allPlacementsReq.go placement}">Submit</bs-button>
<input this="{nameInput}">
{{#if allPlacementsReq.error}}
    There's an error! {{allPlacementsReq.error}}
{{/if}}

Be enough? This would one-way export this into the parent scope.

Contributor

justinbmeyer commented May 6, 2015

Regarding this, would

<gt-placement-request param-new-name="{nameInput.value}" this="{allPlacementsReq}" can-request-done="{notifyDone allPlacementsReq.value}">
</gt-placement-request>
<bs-button can-click="{allPlacementsReq.go placement}">Submit</bs-button>
<input this="{nameInput}">
{{#if allPlacementsReq.error}}
    There's an error! {{allPlacementsReq.error}}
{{/if}}

Be enough? This would one-way export this into the parent scope.

@justinbmeyer

This comment has been minimized.

Show comment
Hide comment
@justinbmeyer

justinbmeyer May 6, 2015

Contributor

cc @daffl where did you get on this for 2.3?

Contributor

justinbmeyer commented May 6, 2015

cc @daffl where did you get on this for 2.3?

@justinbmeyer

This comment has been minimized.

Show comment
Hide comment
@justinbmeyer

justinbmeyer May 6, 2015

Contributor

@daffl checked what you did:

can.view.attr(/\[[\w\.]+\]/, function(el, options) {
        var prop = removeBrackets(el.getAttribute(options.attributeName));
        var name = removeBrackets(options.attributeName, '[', ']');

        can.one.call(el, 'inserted', function() {
            var value = can.viewModel(el);

            if(prop !== 'this' && prop !== '.') {
                value = value.attr(prop);
            }

            options.scope.attr(name, value);
        });
    });

this won't change if the value.attr(prop) changes. In that case, we should listen to changes in it and update the scope.attr.

Contributor

justinbmeyer commented May 6, 2015

@daffl checked what you did:

can.view.attr(/\[[\w\.]+\]/, function(el, options) {
        var prop = removeBrackets(el.getAttribute(options.attributeName));
        var name = removeBrackets(options.attributeName, '[', ']');

        can.one.call(el, 'inserted', function() {
            var value = can.viewModel(el);

            if(prop !== 'this' && prop !== '.') {
                value = value.attr(prop);
            }

            options.scope.attr(name, value);
        });
    });

this won't change if the value.attr(prop) changes. In that case, we should listen to changes in it and update the scope.attr.

@daffl

This comment has been minimized.

Show comment
Hide comment
@daffl

daffl Oct 22, 2015

Contributor

This can be done in 2.3.0 with the new view bindings (http://canjs.com/2.3-pre/docs/can.view.bindings.html)

Contributor

daffl commented Oct 22, 2015

This can be done in 2.3.0 with the new view bindings (http://canjs.com/2.3-pre/docs/can.view.bindings.html)

@daffl daffl closed this Oct 22, 2015

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