Could outlet be made to work with block params ? #10922

Closed
toranb opened this Issue Apr 21, 2015 · 30 comments

Comments

Projects
None yet
5 participants
@toranb
Contributor

toranb commented Apr 21, 2015

Today the outlet hbs helper will blow up if I push a non string value. But w/ block params it would be handy to pass in index for dynamic outlet names/etc.

I assume this isn't supported for a reason. If I'm incorrect ... would the team be open to a PR that allows block param index values (for outlet) ?

{{#each model as |foo index|}}
    {{#link-to "foo.detail" index}}details{{/link-to}}
    {{outlet index}}
{{/each}}
@ef4

This comment has been minimized.

Show comment
Hide comment
@ef4

ef4 Apr 21, 2015

Contributor

I actually think this can be made to work just fine.

The assertion about using a non-quoted argument was due more to historical cleanup -- we used to treat {{outlet "name"}} and {{outlet name}} as equivalent, so the assertion is there to get people to stop doing that. If we think everybody has has time to move to quoted strings, it would be safe to offer the bound argument form.

Contributor

ef4 commented Apr 21, 2015

I actually think this can be made to work just fine.

The assertion about using a non-quoted argument was due more to historical cleanup -- we used to treat {{outlet "name"}} and {{outlet name}} as equivalent, so the assertion is there to get people to stop doing that. If we think everybody has has time to move to quoted strings, it would be safe to offer the bound argument form.

@ef4

This comment has been minimized.

Show comment
Hide comment
@ef4

ef4 Apr 21, 2015

Contributor

In glimmer this feature would probably be about a 5 to 10 line change.

Contributor

ef4 commented Apr 21, 2015

In glimmer this feature would probably be about a 5 to 10 line change.

@toranb

This comment has been minimized.

Show comment
Hide comment
@toranb

toranb Apr 21, 2015

Contributor

Understood - for now it seems like I'll need to fork/maintain my special outlet as this would conflict w/ the dep warnings in place for 1.x

Contributor

toranb commented Apr 21, 2015

Understood - for now it seems like I'll need to fork/maintain my special outlet as this would conflict w/ the dep warnings in place for 1.x

@toranb

This comment has been minimized.

Show comment
Hide comment
@toranb

toranb Apr 21, 2015

Contributor

Any tips for how to avoid forking it? I'm currently trying to see if I can invoke the original outlet after I "stringify" the index. The below blows up currently (mostly looking to let me know if I'm headed in the right direction).

Ember["default"].Handlebars.helpers.outlet.helperFunction.call(this, someNewArgs)
Contributor

toranb commented Apr 21, 2015

Any tips for how to avoid forking it? I'm currently trying to see if I can invoke the original outlet after I "stringify" the index. The below blows up currently (mostly looking to let me know if I'm headed in the right direction).

Ember["default"].Handlebars.helpers.outlet.helperFunction.call(this, someNewArgs)
@ef4

This comment has been minimized.

Show comment
Hide comment
@ef4

ef4 Apr 21, 2015

Contributor

I don't think you have to fork, you can just add a custom helper. Something like:

export function specialOutletHelper(params, hash, options, env) {
  var view = env.data.view;
  var viewClass = view.container.lookupFactory('view:-outlet');
  hash._outletName = params[0];
  options.helperName = 'special-outlet'
  return env.helpers.view.helperFunction.call(this, [viewClass], hash, options, env);
}

This doesn't give you a bound name (if the outlet name parameter changes, we won't rerender). But it does work for your case when you just want to use array indices that will remain stable for the life of the outlet.

Contributor

ef4 commented Apr 21, 2015

I don't think you have to fork, you can just add a custom helper. Something like:

export function specialOutletHelper(params, hash, options, env) {
  var view = env.data.view;
  var viewClass = view.container.lookupFactory('view:-outlet');
  hash._outletName = params[0];
  options.helperName = 'special-outlet'
  return env.helpers.view.helperFunction.call(this, [viewClass], hash, options, env);
}

This doesn't give you a bound name (if the outlet name parameter changes, we won't rerender). But it does work for your case when you just want to use array indices that will remain stable for the life of the outlet.

@ef4

This comment has been minimized.

Show comment
Hide comment
@ef4

ef4 Apr 21, 2015

Contributor

@wycats just pointed out to me that this feature is actually implemented in glimmer already, we just need to decide to remove the legacy assertion

Contributor

ef4 commented Apr 21, 2015

@wycats just pointed out to me that this feature is actually implemented in glimmer already, we just need to decide to remove the legacy assertion

@toranb

This comment has been minimized.

Show comment
Hide comment
@toranb

toranb Apr 21, 2015

Contributor

So I don't need to make a custom HTMLBars helper /register it? (I'm using ember 1.11)

Ember.HTMLBars.registerHelper('custom-outlet', myOutletHelper);

Contributor

toranb commented Apr 21, 2015

So I don't need to make a custom HTMLBars helper /register it? (I'm using ember 1.11)

Ember.HTMLBars.registerHelper('custom-outlet', myOutletHelper);

@ef4

This comment has been minimized.

Show comment
Hide comment
@ef4

ef4 Apr 21, 2015

Contributor

Yes, you would register the function I showed above with something like

Ember.HTMLBars.registerHelper('special-outlet', specialOutletHelper);
Contributor

ef4 commented Apr 21, 2015

Yes, you would register the function I showed above with something like

Ember.HTMLBars.registerHelper('special-outlet', specialOutletHelper);
@toranb

This comment has been minimized.

Show comment
Hide comment
@toranb

toranb Apr 21, 2015

Contributor

The confusing part is that in ES6 land w/ ember-cli you typically "export" out a fn from the helpers directory... but inside ember source I see Ember.HTMLBars.registerHelper for things like outlet. If I register this (as you showed above) how can I expose this for templates in the app itself?

Contributor

toranb commented Apr 21, 2015

The confusing part is that in ES6 land w/ ember-cli you typically "export" out a fn from the helpers directory... but inside ember source I see Ember.HTMLBars.registerHelper for things like outlet. If I register this (as you showed above) how can I expose this for templates in the app itself?

@ef4

This comment has been minimized.

Show comment
Hide comment
@ef4

ef4 Apr 21, 2015

Contributor

I would call registerHelper from app.js.

Contributor

ef4 commented Apr 21, 2015

I would call registerHelper from app.js.

@toranb

This comment has been minimized.

Show comment
Hide comment
@toranb

toranb Apr 21, 2015

Contributor

This is what I have currently that seems to work

export default Ember.HTMLBars.makeBoundHelper(function(params, hash, options, env) {
}
Contributor

toranb commented Apr 21, 2015

This is what I have currently that seems to work

export default Ember.HTMLBars.makeBoundHelper(function(params, hash, options, env) {
}
@toranb

This comment has been minimized.

Show comment
Hide comment
@toranb

toranb Apr 21, 2015

Contributor

Quick update for anyone who might follow

I was able to "access" the custom hbs helper using the export default Ember.HTMLBars.makeBoundHelper syntax above ... but it wasn't providing me a stream like the vanilla outlet helper.

Instead I did what @ef4 suggested above (doing the below in my app.js file) and it works ... with (again) one exception. I had to use _registerHelper instead of registerHelper for some odd reason

var wat = function(params, hash, options, env) {
  var view = env.data.view;
  var property = "main";
  if (params.length > 0) {
      property = params[0];
  }
  var viewClass = view.container.lookupFactory('view:-outlet');
  hash._outletName = property;
  options.helperName = options.helperName || 'outlet';
  return env.helpers.view.helperFunction.call(this, [viewClass], hash, options, env);
};

Ember.HTMLBars._registerHelper('custom-outlet', wat);
Contributor

toranb commented Apr 21, 2015

Quick update for anyone who might follow

I was able to "access" the custom hbs helper using the export default Ember.HTMLBars.makeBoundHelper syntax above ... but it wasn't providing me a stream like the vanilla outlet helper.

Instead I did what @ef4 suggested above (doing the below in my app.js file) and it works ... with (again) one exception. I had to use _registerHelper instead of registerHelper for some odd reason

var wat = function(params, hash, options, env) {
  var view = env.data.view;
  var property = "main";
  if (params.length > 0) {
      property = params[0];
  }
  var viewClass = view.container.lookupFactory('view:-outlet');
  hash._outletName = property;
  options.helperName = options.helperName || 'outlet';
  return env.helpers.view.helperFunction.call(this, [viewClass], hash, options, env);
};

Ember.HTMLBars._registerHelper('custom-outlet', wat);

@toranb toranb closed this Apr 21, 2015

@intuitivepixel

This comment has been minimized.

Show comment
Hide comment
@intuitivepixel

intuitivepixel May 11, 2015

Contributor

@toranb current ember canary (including glimmer) breaks this custom-outlet hack lamentably, have you tried canary yet and got a workaround?

Contributor

intuitivepixel commented May 11, 2015

@toranb current ember canary (including glimmer) breaks this custom-outlet hack lamentably, have you tried canary yet and got a workaround?

@rwjblue

This comment has been minimized.

Show comment
Hide comment
@rwjblue

rwjblue May 11, 2015

Member

Canary allows for bound outlet names.

Member

rwjblue commented May 11, 2015

Canary allows for bound outlet names.

@intuitivepixel

This comment has been minimized.

Show comment
Hide comment
@intuitivepixel

intuitivepixel May 11, 2015

Contributor

@rwjblue this sounds extremely elegant, but how do you use/implement them?

Contributor

intuitivepixel commented May 11, 2015

@rwjblue this sounds extremely elegant, but how do you use/implement them?

@toranb

This comment has been minimized.

Show comment
Hide comment
@toranb

toranb May 11, 2015

Contributor

@rwjblue what is the syntax for "bound outlet names" like you mention? Does this mean the Ember assert that previously blew up was removed in canary?

Contributor

toranb commented May 11, 2015

@rwjblue what is the syntax for "bound outlet names" like you mention? Does this mean the Ember assert that previously blew up was removed in canary?

@ef4

This comment has been minimized.

Show comment
Hide comment
@ef4

ef4 May 11, 2015

Contributor

Yes, the assertion is removed and {{outlet foo}} does the right thing.

Contributor

ef4 commented May 11, 2015

Yes, the assertion is removed and {{outlet foo}} does the right thing.

@ef4

This comment has been minimized.

Show comment
Hide comment
@ef4

ef4 May 11, 2015

Contributor

Was done here: #11029

Contributor

ef4 commented May 11, 2015

Was done here: #11029

@toranb

This comment has been minimized.

Show comment
Hide comment
@toranb

toranb May 11, 2015

Contributor

@ef4 excellent! I'll verify my "hack" works in canary tonight and update the blog post I wrote about it -thanks again!

Contributor

toranb commented May 11, 2015

@ef4 excellent! I'll verify my "hack" works in canary tonight and update the blog post I wrote about it -thanks again!

@intuitivepixel

This comment has been minimized.

Show comment
Hide comment
@intuitivepixel

intuitivepixel May 11, 2015

Contributor

@toranb that's great - you have an early adopter for the hack right here :) thanks!!

Contributor

intuitivepixel commented May 11, 2015

@toranb that's great - you have an early adopter for the hack right here :) thanks!!

@toranb

This comment has been minimized.

Show comment
Hide comment
@toranb

toranb May 11, 2015

Contributor

@rwjblue @ef4 is it possible to use jsbin w/ glimmer yet? If so what is the src for ember to get that version?

Contributor

toranb commented May 11, 2015

@rwjblue @ef4 is it possible to use jsbin w/ glimmer yet? If so what is the src for ember to get that version?

@mixonic

This comment has been minimized.

Show comment
Hide comment
@mixonic

mixonic May 11, 2015

Member

@toranb just use canary.

  • builds.emberjs.com/canary/ember.debug.js
  • builds.emberjs.com/canary/ember-template-compiler.js
Member

mixonic commented May 11, 2015

@toranb just use canary.

  • builds.emberjs.com/canary/ember.debug.js
  • builds.emberjs.com/canary/ember-template-compiler.js
@toranb

This comment has been minimized.

Show comment
Hide comment
@toranb

toranb May 12, 2015

Contributor

@mixonic thanks! With your helpful js I was able to get a mostly working glimmer branch of my nested example

https://github.com/toranb/named-outlet-inside-each-loop-example/tree/glimmer

The only issue I'm still trying to fix/work through is the "index zero" (ie- the first item in the loop).

If anyone uses the example I link to above - be sure to throw out the ember.debug.js/and the compiler after you bower install and replace them with the latest canary build shown above.

Contributor

toranb commented May 12, 2015

@mixonic thanks! With your helpful js I was able to get a mostly working glimmer branch of my nested example

https://github.com/toranb/named-outlet-inside-each-loop-example/tree/glimmer

The only issue I'm still trying to fix/work through is the "index zero" (ie- the first item in the loop).

If anyone uses the example I link to above - be sure to throw out the ember.debug.js/and the compiler after you bower install and replace them with the latest canary build shown above.

@intuitivepixel

This comment has been minimized.

Show comment
Hide comment
@intuitivepixel

intuitivepixel May 12, 2015

Contributor

@toranb I came around the index 0 problem by using the id or the record I'm looping over like {{outlet record.id}} and then in the renderTemplate 'outlet': model.get('id'),

Contributor

intuitivepixel commented May 12, 2015

@toranb I came around the index 0 problem by using the id or the record I'm looping over like {{outlet record.id}} and then in the renderTemplate 'outlet': model.get('id'),

@toranb

This comment has been minimized.

Show comment
Hide comment
@toranb

toranb May 13, 2015

Contributor

@intuitivepixel would you mind doing a quick PR to the glimmer branch for that example?

https://github.com/toranb/named-outlet-inside-each-loop-example/tree/glimmer

I tried to use model.get("id") for the outlet but how did you disconnect outlet? I could reach into the controller.model to get that id but I'm curios what you did :)

Contributor

toranb commented May 13, 2015

@intuitivepixel would you mind doing a quick PR to the glimmer branch for that example?

https://github.com/toranb/named-outlet-inside-each-loop-example/tree/glimmer

I tried to use model.get("id") for the outlet but how did you disconnect outlet? I could reach into the controller.model to get that id but I'm curios what you did :)

@intuitivepixel

This comment has been minimized.

Show comment
Hide comment
@intuitivepixel

intuitivepixel May 13, 2015

Contributor

@toranb there you go: toranb/named-outlet-inside-each-loop-example#1 the PR has two commits, the first I used hat.name and in the second I added and id to the hat model and used {{outlet hat.id}} instead, both versions work just fine, it looks like using 0 as the outlet bound name is what's not working.

Contributor

intuitivepixel commented May 13, 2015

@toranb there you go: toranb/named-outlet-inside-each-loop-example#1 the PR has two commits, the first I used hat.name and in the second I added and id to the hat model and used {{outlet hat.id}} instead, both versions work just fine, it looks like using 0 as the outlet bound name is what's not working.

@toranb

This comment has been minimized.

Show comment
Hide comment
@toranb

toranb May 13, 2015

Contributor

@intuitivepixel thanks for the pull request - I'll update my blog tonight and give you a legit mention :)

Contributor

toranb commented May 13, 2015

@intuitivepixel thanks for the pull request - I'll update my blog tonight and give you a legit mention :)

@intuitivepixel

This comment has been minimized.

Show comment
Hide comment
@intuitivepixel

intuitivepixel May 13, 2015

Contributor

@toranb great! thx! :)

Contributor

intuitivepixel commented May 13, 2015

@toranb great! thx! :)

@toranb

This comment has been minimized.

Show comment
Hide comment
@toranb

toranb May 14, 2015

Contributor

For anyone following along -here is the blog post I put together with help from @ef4 and @intuitivepixel

http://toranbillups.com/blog/archive/2015/04/21/how-to-use-outlets-from-within-your-each-loop/

Contributor

toranb commented May 14, 2015

For anyone following along -here is the blog post I put together with help from @ef4 and @intuitivepixel

http://toranbillups.com/blog/archive/2015/04/21/how-to-use-outlets-from-within-your-each-loop/

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