These are chat archives for canjs/canjs

14th
Sep 2015
direct hangout access
Matthew Phillips
@matthewp
Sep 14 2015 21:02
@/all please join to talk about binding syntax!
Julian
@pYr0x
Sep 14 2015 21:02
so
i am there
where is the link?
Matthew Phillips
@matthewp
Sep 14 2015 21:03
@pYr0x the one justin posted above
Julian
@pYr0x
Sep 14 2015 21:03
ok have it
Matthew Phillips
@matthewp
Sep 14 2015 21:04
if you want to be in the broadcast let me know
Julian
@pYr0x
Sep 14 2015 21:08
i am in ?
Gerard Finnerty
@halcyonandon
Sep 14 2015 21:19
hey, anyone around with a good understanding of using canjs routing properly, I'm hitting a bug, but i think its my using the routing incorrectly
David Luecke
@daffl
Sep 14 2015 21:19
What's the bug?
Gerard Finnerty
@halcyonandon
Sep 14 2015 21:20
In the top-most level of my app, i have the routing configured in a can.Control
in the routes i define each like this

'signin route' : function() {
bootData.duration = 'stop';
var template = can.stache('<signin></signin>');
this.flow.html(template());
},

'faq route' : function() {
bootData.duration = 'stop';
var template = can.stache('<faq></faq>');
this.flow.html(template());
},

'create route' : function() {
var template = can.stache('<create></create>');
this.flow.html(template());
},

then I use 'route' as a failover

'route': function() {

var newHash = '#!signin',
  hash = window.location.hash;

if(bootData.landingPageMode === "create") {
  newHash = '#!create';
} else if(bootData.landingPageMode === "faq") {
  newHash = '#!faq';
}

// This is an ugly fix for firefox where it evaluates the condition but does not load the components
if ((hash !== "#!create" && hash !== "#!faq") || hash.length < 3 ) {
  setTimeout(function() {
    window.location.hash = newHash;
  }, 100);
}

}

so first thing... I didn't think can.route.attr() was necessary to use, is it?
second... the bug... is two parts... on first click of create, it fails and refreshes back to sign in in all browsers, i have no idea why, but im still trying to step through to the root cause....
the other bug is when the browser tab is out of focus and a timeout occurs, we direct the user back to signin, but instead it loads everything except the components that trigger on route, so we end up with an empty shell of a page
David Luecke
@daffl
Sep 14 2015 21:24

You can make this much easier in template:

can.route(':page', { page: 'create' });
flow.html(can.view('main.stache', can.route));

main.stache:

{{#eq page 'signin'}}
  <app-signin></app-signin>
{{/eq}}
{{#eq page 'faq'}}
  <app-faq></app-faq>
{{/eq}}
{{#eq page 'faq'}}
  <app-create></app-create>
{{/eq}}
Gerard Finnerty
@halcyonandon
Sep 14 2015 21:25
'page automatically gets into the component's viewModel like that? cool
nvm lol
David Luecke
@daffl
Sep 14 2015 21:27
Oh also, it should throw a warning when using component tag names that aren't separated with a dash
Gerard Finnerty
@halcyonandon
Sep 14 2015 21:27
you pass in can.route like that and that adds page to viewModel?
David Luecke
@daffl
Sep 14 2015 21:28
Yes, it's the data you're rendering the template with.
can.route is observable, too so if you change the route the template will update
Gerard Finnerty
@halcyonandon
Sep 14 2015 21:28
component tag names that arent separated with a dash? you mean someComponent turns into some-component or something else?
David Luecke
@daffl
Sep 14 2015 21:29
I mean <faq></faq> should be <app-faq></app-faq>
Gerard Finnerty
@halcyonandon
Sep 14 2015 21:29
oh we do this for hundreds of components and I havent seen any warnings
David Luecke
@daffl
Sep 14 2015 21:30
Hm... maybe it didn't give the warning in older versions. It works but the HTML5 spec says that custom elements should have a dash in them.
Gerard Finnerty
@halcyonandon
Sep 14 2015 21:31
so does that work automatically or do i have to change all the instances? 'e.g. tag: 'landing' has to become tag: 'app-landing'
David Luecke
@daffl
Sep 14 2015 21:34
Yeah you'd have to change them. Not super urgent if it works right now but I'd recommend it to be more future-proof.
Gerard Finnerty
@halcyonandon
Sep 14 2015 21:35
ok thanks
so then what about dynamically setting the default route... so if my routes are all defined, but the user hits the page with no route, i need to dynamically construct the route based on various conditions
'route': function(){} gets hit even when a valid route is present, so we need to do a check to see if a route is defined there, is there a cleaner way?
or is that even right?
Matthew Phillips
@matthewp
Sep 14 2015 21:38
I would avoid using route listeners in controllers altogether
and use routing like @daffl suggested above
David Luecke
@daffl
Sep 14 2015 21:39
I did this recently: if(can.isEmptyObject(can.route.attr('route')) { console.log('No route matched') }
Mohamed Cherif Bouchelaghem
@cherifGsoul
Sep 14 2015 21:39
I have bad internet connection I can not be in the talk :(
Gerard Finnerty
@halcyonandon
Sep 14 2015 21:42
so inside the component, on inserted (or init) I should do a check like @daffl suggested and set the default route that way... and no event handlers for the route
David Luecke
@daffl
Sep 14 2015 21:43
I would do that at the application level.
if(can.route.attr('page') !== 'home' && user.hasTodos) {can.route.attr('page', 'create'); }
Gerard Finnerty
@halcyonandon
Sep 14 2015 21:50
ok cool, ill try this approach and see if that fixes things
@daffl actually one more question... where should can.route.ready(); be called?
App = can.Control.extend({
init : function(element) {
var template = can.stache('<app></app>');
// hash = '#!signin';
this.element.html(template());
this.flow = $('#flow');
can.route.ready();
David Luecke
@daffl
Sep 14 2015 21:52
Looks right to me
Gerard Finnerty
@halcyonandon
Sep 14 2015 21:52
ok cool thanks
Julian
@pYr0x
Sep 14 2015 21:58
createPbAndMail: function(context){}
context().attr('wwpnu_id')
can-click="{createPbHaAndMail}"
kiwi1342
@kiwi1342
Sep 14 2015 22:05
hi
one small question: is it possible to access and modify a component's viewModel attr?
triggering the view refresh?
Gerard Finnerty
@halcyonandon
Sep 14 2015 22:09
@kiwi1342 Do you mean from outside the component?
kiwi1342
@kiwi1342
Sep 14 2015 22:09
yes
Julian
@pYr0x
Sep 14 2015 22:10
index
key
kiwi1342
@kiwi1342
Sep 14 2015 22:11
var vm = can.Map.extend({ init: function(){ this.attr('name','Richard') } })
Gerard Finnerty
@halcyonandon
Sep 14 2015 22:11
That's not something I do, since I pass observables into the components, but yeah, you can access a component's viewModel on the element itself, like $('component-name').viewModel()
kiwi1342
@kiwi1342
Sep 14 2015 22:13
component name?
Gerard Finnerty
@halcyonandon
Sep 14 2015 22:13
yeah the tag name of your component used as the selector
kiwi1342
@kiwi1342
Sep 14 2015 22:13
oh sorry the tag name
:+1:
thx perfect :)
Gerard Finnerty
@halcyonandon
Sep 14 2015 22:15
cool
@daffl what about routing inclusion ... import 'can/control/route'; vs import 'can/route'; is there any reason to use the route under control or vice versa
David Luecke
@daffl
Sep 14 2015 22:48
can/control/route is an old plugin (that depends on can/route). I don't use it in new projects anymore because pretty much everything can be done in the template based on your application state (which can map to routes) now
Gerard Finnerty
@halcyonandon
Sep 14 2015 23:02
@daffl ok cool thanks
Gerard Finnerty
@halcyonandon
Sep 14 2015 23:21
@daffl changing the route in the manner you suggested prevents direct changes to the hashbang value... so if a user tries to modify the hash bang to the url they want or a link just changes the window.location.hash, it won't work and that's expected?
David Luecke
@daffl
Sep 14 2015 23:22
I'm not sure what you mean. If somebody clicks a link or updates the hash otherwise the route will update accordingly.
Gerard Finnerty
@halcyonandon
Sep 14 2015 23:25
hrm, that's not the behavior i see
maybe its how I've done it

var App = can.Control.extend({
init : function(element) {
can.route.ready();

var route = can.route.attr('page');

if(can.route.attr('page') !== 'signin') {
  can.route.attr('page', 'signin');
}

var template = can.stache('<app page="{page}"></app>');

this.element.html(template({"page" : can.route.attr('page') }));
this.flow = $('#flow');

},

should i pass can.route as a whole into the viewModel? when I tried that I couldn't access the page attr in the component's viewModel
and when i made a hashbang change regardless of the component, 'init' never gets run again
which i guess could be expected
David Luecke
@daffl
Sep 14 2015 23:28
You are rendering the template with the actual value. You have to pass an observable.
this.element.html(template(can.route));
Gerard Finnerty
@halcyonandon
Sep 14 2015 23:32
@daffl oh ok, I see it working, but what about passing it further down into other components... so that first guy gets his, but one of his children needs it too and that child is instantiated inside the parent's template
Gerard Finnerty
@halcyonandon
Sep 14 2015 23:49
yeah, the way im doing it def is not working well at all
Kevin Phillips
@phillipskevin
Sep 14 2015 23:50
you can pass it like this.element.html(template({ route: can.route })); which might make it a little easier to pass around to child components
David Luecke
@daffl
Sep 14 2015 23:50
Well the parent just keeps passing page="{page}" to its child components
If they need it.
Gerard Finnerty
@halcyonandon
Sep 14 2015 23:51
yeah that's what im doing... its odd, i see it working then i try again and it stops working... ill keep playing with it