These are chat archives for canjs/canjs

23rd
Mar 2016
Julian
@pYr0x
Mar 23 2016 00:04
@jeroencornelissen i thought that your question i have seen once. http://forums.donejs.com/t/modifying-view-after-rendering-finishes/52 I posted a possible solution. Maybe you have to restructure your code.
Jeroen Cornelissen
@jeroencornelissen
Mar 23 2016 08:22
:point_up: 22 maart 2016 17:27
@cherifGsoul @pYr0x Do you mean something like this: http://jsbin.com/tuciqivuxi/1/edit?html,js,output
Look at the clicky function. It feels kind of wrong removing the component and inserting it again. I think the power of CanJS is the live binding, change one property and my app rerenders automaticilly.
Jeroen Cornelissen
@jeroencornelissen
Mar 23 2016 08:53
@dbleier @pYr0x I added a reply to the existing forum topic:
http://forums.donejs.com/t/modifying-view-after-rendering-finishes/52/3
Julian
@pYr0x
Mar 23 2016 09:02
@jeroencornelissen my jsbin example didnt help you?
and check on the my-input inserted event
is this also fired only once?
Jeroen Cornelissen
@jeroencornelissen
Mar 23 2016 09:11
@pYr0x this could work, I already have a component for each input type so I could provide a focus attr from the backend.
I console log the inserted event and that gets triggered every time so this could work :+1:
Julian
@pYr0x
Mar 23 2016 09:24
other option is to use autofocus
Jeroen Cornelissen
@jeroencornelissen
Mar 23 2016 09:33
@pYr0x autofocus only seems to werk first time, not when switching between forms.
With the extra focus attribute I can make it work! :clap:
Julian
@pYr0x
Mar 23 2016 09:35
good.. if you can add your working example to the forum, would be nice
or provide a solution
Mohamed Cherif Bouchelaghem
@cherifGsoul
Mar 23 2016 09:57
@jeroencornelissen thank you for submiting it in donejs forums
This message was deleted
Christopher Oliphant
@RALifeCoach
Mar 23 2016 10:41
in the docs it recommends including css files with components
how best to do that?
is there some way of bringing the file into the component?
Guido Smeets
@gsmeets
Mar 23 2016 10:42
Depending on how much css you have I wouldn't bother
Julian
@pYr0x
Mar 23 2016 11:02
dont understand the question...
Christopher Oliphant
@RALifeCoach
Mar 23 2016 11:19
there is a property on component for template, it would be nice to have a property for css - that could be a css, less or sass string or file
Julian
@pYr0x
Mar 23 2016 11:20
what do you mean with property?
Christopher Oliphant
@RALifeCoach
Mar 23 2016 11:21
can.Component.extend({
tag: ‘tag-name’
*template*: can.view(’path to stache file’)
wwould tag and template not be properties of the component?
Julian
@pYr0x
Mar 23 2016 11:22
include css or less import 'path/to/style.css';
Christopher Oliphant
@RALifeCoach
Mar 23 2016 11:23
except this project does not use steal
Julian
@pYr0x
Mar 23 2016 11:23
or require();
tried <can-import>?
in the template
Christopher Oliphant
@RALifeCoach
Mar 23 2016 11:27
interesting suggestion, can I use it to import a script as well?
Julian
@pYr0x
Mar 23 2016 11:27
i think so
try it
Christopher Oliphant
@RALifeCoach
Mar 23 2016 11:28
I will, do you know the docs mean when they say that can-import only works with can.autorender?
Julian
@pYr0x
Mar 23 2016 11:29
it says with can.autorender or the system plugin
Christopher Oliphant
@RALifeCoach
Mar 23 2016 11:30
even still, I am not sure what that means
you have to use stache can/view/stache/system
it means, it works with stache templates and a script tag that is tagged as autorender
Christopher Oliphant
@RALifeCoach
Mar 23 2016 11:32
This project is not using steal or system. There is no DI.
Julian
@pYr0x
Mar 23 2016 11:32
you dont need steal
or system
it works with stache
which is provided by stache
Christopher Oliphant
@RALifeCoach
Mar 23 2016 11:34
okay - I will play with it and see what I can figure out
Christopher Oliphant
@RALifeCoach
Mar 23 2016 11:57
I apologize for asking so many questions. And I now have another one.

I have a component like so:

<feature-icon type="photo" types="photos" isActive="{{isActive}}" hasMedia="{{hasMediaContent('photos')}}" profilesURL="options.profilesURL"></feature-icon>

The ‘hasMedia’ attribute changes, but the binding to ‘hasMedia’ doesn’t fire.

    can.Component.extend({
        tag: 'feature-icon',
        template: can.view('/modules/feature-icon/feature-icon.stache'),
        viewModel: can.Map.extend({
            init: function () {
                this.bind('hasMedia', function () {
                    debugger;
                });
            },
            hasMedia: false
        })
    });
Christopher Oliphant
@RALifeCoach
Mar 23 2016 12:02
when I examine the element I can see that hasMedia has changed
Julian
@pYr0x
Mar 23 2016 12:08
try
better use the define plugin... getter and setter
for making sideeffects
Christopher Oliphant
@RALifeCoach
Mar 23 2016 12:11
The first suggestion didn’t work.
    can.Component.extend({
        tag: 'feature-icon',
        template: can.view('/modules/components/feature-icon/feature-icon.stache'),
        viewModel: can.Map.extend({
            hasMedia: false
        }),
        events: {
            '{viewModel} hasMedia': function () {
                debugger;
            }
        }
    });
Julian
@pYr0x
Mar 23 2016 12:14
and how do you change hasMedia?
please notice, that the viewModel is an external var
Christopher Oliphant
@RALifeCoach
Mar 23 2016 12:16
It is contained within another component and set by the parent when the data changes.
In debug, when I examine the component, I can see the value in the attribute has changed, but I don’t see the change within the component.
    var Model = can.Map.extend({
        define: {
            hasMedia: {
                type: 'boolean',
                set: function () {
                    debugger;
                }
            }
        }
    });
    can.Component.extend({
        tag: 'feature-icon',
        template: can.view('/modules/components/feature-icon/feature-icon.stache'),
        viewModel: Model
    });
Christopher Oliphant
@RALifeCoach
Mar 23 2016 12:22
Still no luck
BTW, I included can/stache/system, but <can-import> didn’t work
Julian
@pYr0x
Mar 23 2016 12:32
how do you mean , inclueded can/stache/system?
how do you use canjs?
AMD?
global?
Christopher Oliphant
@RALifeCoach
Mar 23 2016 12:33
global
Julian
@pYr0x
Mar 23 2016 12:33
and how could you include can/stache/system ?
Christopher Oliphant
@RALifeCoach
Mar 23 2016 12:33
so when I built the custom file, I included can/stache/system
Mohamed Cherif Bouchelaghem
@cherifGsoul
Mar 23 2016 12:34
I think a dependency manager (steal,requirejs,webpack) is required to use can/stache/system
Julian
@pYr0x
Mar 23 2016 12:35
ok
Christopher Oliphant
@RALifeCoach
Mar 23 2016 12:37
@cherifGsoul any suggestions on my delema
Mohamed Cherif Bouchelaghem
@cherifGsoul
Mar 23 2016 12:37
@RALifeCoach I didnt follow from the bginning
:/
Christopher Oliphant
@RALifeCoach
Mar 23 2016 12:39

okay - I have a component:

<feature-icon type="article" types="articles" 
                                  isActive="{{isActive}}" 
                                  hasMedia="{{hasMediaContent('articles')}}" 
                                  profilesURL="options.profilesURL"></feature-icon>

with the component defined as:

    var Model = can.Map.extend({
        define: {
            hasMedia: {
                type: 'boolean',
                set: function () {
                    debugger;
                }
            }
        }
    });
    can.Component.extend({
        tag: 'feature-icon',
        template: can.view('/modules/components/feature-icon/feature-icon.stache'),
        viewModel: Model
    });

The debugger is never called

I know the value in hasMedia is initially set to false and is later set to true
Mohamed Cherif Bouchelaghem
@cherifGsoul
Mar 23 2016 12:41
use has-mediaas attribute in the component
Christopher Oliphant
@RALifeCoach
Mar 23 2016 12:41
The attribute value never seems to get changed in the viewModel
Mohamed Cherif Bouchelaghem
@cherifGsoul
Mar 23 2016 12:41
change it to what I sugget
<feature-icon type="article" types="articles" 
                                  is-active="{{isActive}}" 
                                  has-media="{{hasMediaContent('articles')}}" 
                                  profiles-URL="options.profilesURL"></feature-icon>
Christopher Oliphant
@RALifeCoach
Mar 23 2016 12:42
Thanks - that was all it took
Mohamed Cherif Bouchelaghem
@cherifGsoul
Mar 23 2016 12:42
works?
Christopher Oliphant
@RALifeCoach
Mar 23 2016 12:44
It is better, not sure if all is working yet
Julian
@pYr0x
Mar 23 2016 12:44
@cherifGsoul great job :)
Veni vidi vici
:clap:
Mohamed Cherif Bouchelaghem
@cherifGsoul
Mar 23 2016 12:45
thank you I dont know if those points exist in the docs
Christopher Oliphant
@RALifeCoach
Mar 23 2016 12:46
Yes - it is working now. the attribute is has-media, but when I use it in the stache file it is hasMedia. A bit confusing.
Mohamed Cherif Bouchelaghem
@cherifGsoul
Mar 23 2016 12:48
@RALifeCoach it'scanjs recommandation properties camel cased like hasMediaand template attributes hypenated like has-media
dont be confused bro :)
Christopher Oliphant
@RALifeCoach
Mar 23 2016 12:49
I am easily confused. (And I am having a lot of fun.)
I just hope I am not being too much of a bother. I really appreciate all the assistance I am getting from folks here.
Matthew Phillips
@matthewp
Mar 23 2016 12:53
Every time I come here and see 50+ recent messages i'm terrified but mostly excited :)
CanJS is blowing up!
Mohamed Cherif Bouchelaghem
@cherifGsoul
Mar 23 2016 12:59
@matthewp we are the night watch :D
but it's the efternoon here
Matthew Phillips
@matthewp
Mar 23 2016 12:59
hehe
Christopher Oliphant
@RALifeCoach
Mar 23 2016 13:18
Me again. I am trying to access the view model from an event.
the view model has a function, the events tries:
this.viewModel.vmFunction();
The message is vmFunction is not a function
If I break at that statement and add a watch, this.viewModel.vmFunction returns undefined
Mohamed Cherif Bouchelaghem
@cherifGsoul
Mar 23 2016 13:22
@RALifeCoach maybe full code (component, template) can help to have a quick answer
Christopher Oliphant
@RALifeCoach
Mar 23 2016 13:23
Component:
    can.Component.extend({
        tag: 'player-row',
        template: can.view('/modules/components/player-row/player-row.stache'),
        helpers: helpers,
        events: {
            '.add-to-favorite click': function () {
                this.viewModel.callParent('onPinPlayer');
            }
        }
Map:
    var Map = MapBase.extend({
        define: {
            options: {
                Type: OptionsMap
            },
            pid: {
                type: 'string'
            },
            player: {
                Type: PlayerMap
            },
        },

        callParent: function (method) {
            this.attr(method)();
        },
Mohamed Cherif Bouchelaghem
@cherifGsoul
Mar 23 2016 13:26
@RALifeCoach you dont have a viewModel in your component
Christopher Oliphant
@RALifeCoach
Mar 23 2016 13:26
Inserted via:
            this.playerRowMap = new Map(data);
            var template = can.stache('<player-row id="player-row-' + this.pid + '"></player-row>');
            this.container.append(template(this.playerRowMap));
the view model is inserted as shown in the last snippet. When I look at the view model in debug, I can see the various properties
Mohamed Cherif Bouchelaghem
@cherifGsoul
Mar 23 2016 13:27
I dont think is in the component scope
:/
can.Component.extend({
        tag: 'player-row',
        template: can.view('/modules/components/player-row/player-row.stache'),
       viewModel:Map,
        helpers: helpers,
        events: {
            '.add-to-favorite click': function () {
                this.viewModel.callParent('onPinPlayer');
            }
        }
Christopher Oliphant
@RALifeCoach
Mar 23 2016 13:28
and there are other functions on the view model that are used by the stache template - and those work
The component is in a separate file from the map and they are in separate files from the main code. I wanted to keep that separation.
which leaves me with the problem of populating the viewModel with data.
Mohamed Cherif Bouchelaghem
@cherifGsoul
Mar 23 2016 13:30
Yes you can seperate ViewModelmodule
in your component this.viewModel in the component can have only the base viewModel without your VMmethods
Christopher Oliphant
@RALifeCoach
Mar 23 2016 13:31
How do I insert data into the view model?
Mohamed Cherif Bouchelaghem
@cherifGsoul
Mar 23 2016 13:31
via attributes
attributes in the component
Christopher Oliphant
@RALifeCoach
Mar 23 2016 13:33
This model is built with objects and objects within objects and it has many, many elements. It wouldn’t make sense to put all those into attributes.
Mohamed Cherif Bouchelaghem
@cherifGsoul
Mar 23 2016 13:34
:)
Christopher Oliphant
@RALifeCoach
Mar 23 2016 13:36
I have read that. What are you trying to tell me?
Mohamed Cherif Bouchelaghem
@cherifGsoul
Mar 23 2016 13:36
I want to tell you it makes sens :)
maybe I didnt understand well what are you looking for
Christopher Oliphant
@RALifeCoach
Mar 23 2016 13:37
I am to create a stache element with 100+ attributes?
Mohamed Cherif Bouchelaghem
@cherifGsoul
Mar 23 2016 13:37
you want to pass all of theme to a component?
Christopher Oliphant
@RALifeCoach
Mar 23 2016 13:38
yes
it’s a big piece of code!
Mohamed Cherif Bouchelaghem
@cherifGsoul
Mar 23 2016 13:38
those attrs values are loaded from the server I supose?
Christopher Oliphant
@RALifeCoach
Mar 23 2016 13:39
You suppose correctly. :-)
Mohamed Cherif Bouchelaghem
@cherifGsoul
Mar 23 2016 13:39
In this case you need a can.Model
I hope you have one
Christopher Oliphant
@RALifeCoach
Mar 23 2016 13:40
No I do have one. In this case the data is being retrieved by another module all together and being passed to this module. (The original file contains many rows. This module is just one row.)
So can.Model will not help.
I could create the properties as an JSON object and return it via a fixture - but this is now getting very complicated
Mohamed Cherif Bouchelaghem
@cherifGsoul
Mar 23 2016 13:43
fixtures for production code?
Christopher Oliphant
@RALifeCoach
Mar 23 2016 13:43
exactly - not something I want to do
Therefore I need another suggestion.
I currently instantiate the Map outside of the component and then pass the map into the template when adding the stache template into the page. That way I can update the map data and it is reflected in the html.
Christopher Oliphant
@RALifeCoach
Mar 23 2016 13:48
Everything was working until I tried to wire in an event. The event was originally being wired through jQuery bind’s. I could continue to use that, but I wanted to wire the event into the component.
@cherifGsoul any suggestions?
Mohamed Cherif Bouchelaghem
@cherifGsoul
Mar 23 2016 13:52
the case is complicated
Kevin Phillips
@phillipskevin
Mar 23 2016 13:52
sorry to recap, your problem is that this.viewModel is undefined when you set it up like template(this.playerRowMap) ?
Christopher Oliphant
@RALifeCoach
Mar 23 2016 13:53
The viewModel is defined. But the attrs are buried. and I can’t access them via this.viewModel.attr(‘xxx’).
Mohamed Cherif Bouchelaghem
@cherifGsoul
Mar 23 2016 13:54
@phillipskevin here is the component
 can.Component.extend({
        tag: 'player-row',
        template: can.view('/modules/components/player-row/player-row.stache'),
        helpers: helpers,
        events: {
            '.add-to-favorite click': function () {
                this.viewModel.callParent('onPinPlayer');
            }
        }
the component viewModel prop is emplty
Kevin Phillips
@phillipskevin
Mar 23 2016 13:54
right, I saw that
Mohamed Cherif Bouchelaghem
@cherifGsoul
Mar 23 2016 13:55
as I understand he wants to copy other external viewModel properties to component props
Christopher Oliphant
@RALifeCoach
Mar 23 2016 13:55
when I break on that statement and watch on this.viewModel it says it is a Constructor. When I open the object I see _data, when I open _data, I see %root, when I open that I see my properties.
Mohamed Cherif Bouchelaghem
@cherifGsoul
Mar 23 2016 13:56
so this.viewModel.attr('%root').attr('prop')
Christopher Oliphant
@RALifeCoach
Mar 23 2016 13:57
That works.
That isn’t exactly intuitive, but it works. Thank-you.
Kevin Phillips
@phillipskevin
Mar 23 2016 14:00
I think it would simplify things a lot if we could figure out a way to pass the viewmodel in the conventional way
Christopher Oliphant
@RALifeCoach
Mar 23 2016 14:05
Actually, this is a really nice way of handling things. With the map being instantiated outside of the component lets me update the map as needed and that automatically updates the html. For really large systems and legacy systems, this is a real boon.
Mohamed Cherif Bouchelaghem
@cherifGsoul
Mar 23 2016 14:07
@RALifeCoach I know you are converting a legacy app, but things withcanjs can be done in simpler way
Christopher Oliphant
@RALifeCoach
Mar 23 2016 14:09
There is a huge difference between writing new code and a slow transition in an existing legacy system. Especially when the legacy system has 100’s of thousands of lines of code. To make the tool really useful, these features become really import in these situations.
Mohamed Cherif Bouchelaghem
@cherifGsoul
Mar 23 2016 14:10
@RALifeCoach yes, we are happy we can help you :)
Christopher Oliphant
@RALifeCoach
Mar 23 2016 14:11
In fact, to make a few changes to make this simpler could greatly extend the reach of this tool into other companies and environments.
Kevin Phillips
@phillipskevin
Mar 23 2016 14:18
please feel free to open issues
Christopher Oliphant
@RALifeCoach
Mar 23 2016 15:56

I’m back. I am trying to fire an event. Inside the component I have:

        events: {
            'highlightplayer': function () {
                debugger;
            },

and in the parent module I have:

$(#myId’).trigger(‘highlightplayer’);

I also tried:

can.event.dispatch.call($(‘myId’), ‘highlightplayer’);
myId is assigned in the stache fragment for the component
Mohamed Cherif Bouchelaghem
@cherifGsoul
Mar 23 2016 15:57
'#myId highlightplayer': function () {
                debugger;
            },
Christopher Oliphant
@RALifeCoach
Mar 23 2016 15:58
okay - I used it without the #myId because the docs say:
events: {
    "click" : function(){
      var currentMessage = this.viewModel.attr("message");
      this.viewModel.attr("message", currentMessage+ "!")
    }
  }
Mohamed Cherif Bouchelaghem
@cherifGsoul
Mar 23 2016 15:59
It listens to click event on the component tag
Christopher Oliphant
@RALifeCoach
Mar 23 2016 15:59
The id in my case isn’t fixed. It is actually ‘xxx-‘ + pid
Mohamed Cherif Bouchelaghem
@cherifGsoul
Mar 23 2016 16:00
use classes
class="js-my-el"
'.js-my-el highlightplayer': function () {
                debugger;
            }
Kevin Phillips
@phillipskevin
Mar 23 2016 16:01
you can put the event in your template also
Christopher Oliphant
@RALifeCoach
Mar 23 2016 16:01
but the component is repeated many times on the page - therefore the class would be repeated
Kevin Phillips
@phillipskevin
Mar 23 2016 16:01
($highlightPlayer)=“highlightPlayer”
Christopher Oliphant
@RALifeCoach
Mar 23 2016 16:01
I only want the change to apply to this row
that’s why the id is distinct
@phillipskevin isn’t that discouraged due to the performance impact?
Kevin Phillips
@phillipskevin
Mar 23 2016 16:05
only if you’re going to have thousands of this component
Christopher Oliphant
@RALifeCoach
Mar 23 2016 16:05
If I specify it as you indicated, then I can use the event as shown above?
Kevin Phillips
@phillipskevin
Mar 23 2016 16:06
if you do it that way, highlightPlayer would be a function on your viewmodel
Christopher Oliphant
@RALifeCoach
Mar 23 2016 16:06
and how do I fire it as an event from outside the component?
$.trigger
or can.trigger
Christopher Oliphant
@RALifeCoach
Mar 23 2016 16:21
Kevin Phillips
@phillipskevin
Mar 23 2016 16:27
no, it doesn't
the ($highlight)=“highlight” has to be on the same element you’re triggering the event on
Christopher Oliphant
@RALifeCoach
Mar 23 2016 16:28
right - thanks
Kevin Phillips
@phillipskevin
Mar 23 2016 16:28
no problem
Thomas Sieverding
@Bajix
Mar 23 2016 23:21
@RALifeCoach How’s the project coming along?