These are chat archives for canjs/canjs

14th
Jun 2016
Ilya Fadeev
@ilyavf
Jun 14 2016 03:45

@leoj3n: some libs require some html to be a direct child of something (e.g. SemanticUI wants its menus and page content "pusher" to be a direct child of body), and I want to add some behaviour to it using can.Component, but it adds a component tag wrapper.

@matthewp: yes, attr is what I am using right now, but its a bit ugly because I need to control multiple siblings and a tagless can.Component would be just ideal. Do you mind to reference the issue please? I was not able to find it...

Ilya Fadeev
@ilyavf
Jun 14 2016 04:31

Related question about tagless-like components: is it possible to implement a feature for can.Component being invoked not on a custom tagname, but on an attribute value (similar to attr)?
Like AngularJS allows directives (==can.Component) to be invoked by tagname/attribute/className.

<div can-component="my-component"></div>

can.Component.extend({
    attrValue: "my-component", ...
})

How would I use can.view.attr to achieve this? E.g.:

// Template:
<div can-component="my-component" my-prop="Testing"><p>{{myProp}}</p></div>

// Attr:
import controls from "myControls";
can.view.attr('can-component', function( el, attrData ) {
    let controlName = attrData["can-component"],
        control = controls[controlName];
    new control(el);
});

// Controls module:
export default {"my-component": can.Control.extend({...},{...}), ...}
Ilya Fadeev
@ilyavf
Jun 14 2016 05:01

(editing expired)

let controlName = el.getAttribute("can-component")

The same way I can read value for my-prop:

let myProp = attrData.scope.attr(el.getAttribute("my-prop"));  // = "Testing"

But el's innerHTML won't have '{{myProp}}' and I cannot use stache to render it as a template with my values as a viewModel...

Fred Daoud
@foxdonut
Jun 14 2016 11:29
element.html(htmlString) does not render the correct html when htmlString does not have a single root element, for example <li>...</li><li>...</li>. Is this a known bug in CanJS?
qantourisc
@qantourisc
Jun 14 2016 11:31
@foxdonut So what is your element in "element.html(..." ? ps(this sounds like a jquery question)
Matthew Phillips
@matthewp
Jun 14 2016 11:47
@ilyavf canjs/canjs#2386
Fred Daoud
@foxdonut
Jun 14 2016 12:04
@qantourisc indeed it is a jquery plugin (multiselect).
just to clarify, make sure I understand... what do you mean by "a jquery question"?
I should be more clear, when I say "known bug in CanJS" I am referring to the html modifier in can.view. That is what is causing the problem.
qantourisc
@qantourisc
Jun 14 2016 12:29
@foxdonut https://canjs.com/docs/can.view.elements.html <= does not list .html(
Also what are the arguments / object where you are applying this function to ?
I can imagen [ el, el].html( ) going bad
Fred Daoud
@foxdonut
Jun 14 2016 12:33
@qantourisc I am talking about this: https://canjs.com/docs/jQuery.fn.html.html
Extending the original jQuery().html() to render can.view templates as the content of each matched element.
qantourisc
@qantourisc
Jun 14 2016 12:33
This message was deleted
Fred Daoud
@foxdonut
Jun 14 2016 12:34
pardon?
qantourisc
@qantourisc
Jun 14 2016 12:34
Does it work with jquery.html() ?
Fred Daoud
@foxdonut
Jun 14 2016 12:35
yes.
qantourisc
@qantourisc
Jun 14 2016 12:35
Also what is "does not render correctly" ?
Fred Daoud
@foxdonut
Jun 14 2016 12:35
if I comment out the 'html' modifier in the canjs library, it works.
qantourisc
@qantourisc
Jun 14 2016 12:37
Ow: you should rephrase your question if I got it correctly: jquery.fn.html plugin break jquerie's .html ?
Fred Daoud
@foxdonut
Jun 14 2016 12:37
I'll be more specific. The code in the jquery multiselect has an element which references a <ul>. The code does element.html(htmlString) where htmlString is <li>...</li><li>...</li>. Now, say there are 16 <li> in htmlString. With CanJS "taking over" the html function, it only renders 8 of them. It drops every other <li>. Now, if I hack htmlString to be <div><li>..</li>...</div>, thus have a single root element, then it works fine.
@qantourisc : no, it is CanJS's html modifier that is breaking jquery's html.
qantourisc
@qantourisc
Jun 14 2016 12:38
well that's what I meant
Fred Daoud
@foxdonut
Jun 14 2016 12:38
sorry, my apologies
qantourisc
@qantourisc
Jun 14 2016 12:39
(That doesn't mean I expressed it clearly ;) )
Fred Daoud
@foxdonut
Jun 14 2016 12:39
so it seems to be that CanJS's modifier expects a single root element in htmlString. That breaks other jquery code, so seems like a bug to me.
qantourisc
@qantourisc
Jun 14 2016 12:39
I would say yes, search in the bugs or report one ?
Fred Daoud
@foxdonut
Jun 14 2016 12:40
I tried searching but it's not easy ;) also, I didn't want to duplicate if this is a known issue, thus I figured I'd ask here first :)
qantourisc
@qantourisc
Jun 14 2016 12:40
I'm to green
Fred Daoud
@foxdonut
Jun 14 2016 12:40
I know that modifiers are being deprecated in 3.0.0
but that doesn't help me for these problems that I am facing today on a real-world application ;)
qantourisc
@qantourisc
Jun 14 2016 12:42
I don't know in what situation you are using them, els.each might be a workaround
Fred Daoud
@foxdonut
Jun 14 2016 12:42
I only got the impression that the problem might be about the single root node because I know React doesn't accept a component unless it has a single root node. Hacking the jquery multiselect code to have a top-level <div> is a workaround, but it's ugly
A) it means hacking a jquery library to workaround a CanJS bug
qantourisc
@qantourisc
Jun 14 2016 12:42
I mean hack canjs
Fred Daoud
@foxdonut
Jun 14 2016 12:42
B) <div> is not really a valid child node of <ul>
Yeah but.. I'm afraid fixing this bug without breaking anything else is CanJS is beyond my means and ability right now..!
qantourisc
@qantourisc
Jun 14 2016 12:43
Then find another way ?
Fred Daoud
@foxdonut
Jun 14 2016 12:44
I have A) the <div> workaround, B) using innerHTML = htmlString, or C) hack CanJS to "preserve" the original functions with a prefix, e.g. jquery_html and then hack the library to call that instead of html
I do have workarounds, and I can get by today with one of them, but none of them are the real solution, I think this needs to be addressed in CanJS.
Kevin Phillips
@phillipskevin
Jun 14 2016 12:53
@foxdonut is there an issue open for this?
Fred Daoud
@foxdonut
Jun 14 2016 13:13
@phillipskevin I looked through the open issues, it doesn't look like there is one.
Kevin Phillips
@phillipskevin
Jun 14 2016 13:14
sorry, I didn’t scroll up far enough to see you already talked about this
go ahead and open a new issue
if it’s a duplicate, someone will close it and point you to the original issue
don’t worry about creating duplicate issues
Fred Daoud
@foxdonut
Jun 14 2016 13:18
will do, thank you @phillipskevin
Fred Daoud
@foxdonut
Jun 14 2016 14:12
@phillipskevin : before I create the issue, do you mind having a quick look at this codepen, i.e. is it a valid code representation of the issue? http://codepen.io/foxdonut/pen/PzNXOW?editors=1010
Kevin Phillips
@phillipskevin
Jun 14 2016 14:15
sure, I can take a look
Kevin Phillips
@phillipskevin
Jun 14 2016 14:21
is there any reason not to just call $(element).somePlugin({}); in init?
to answer your original question, I think your codepen displays the issue just fine
qantourisc
@qantourisc
Jun 14 2016 14:28
:clap: for making a good testcase
Fred Daoud
@foxdonut
Jun 14 2016 14:38
@phillipskevin you ask a good question. at the time the code was written, {{(el) -> el.someFunction()}} was idiomatic, or at least that practice was not on its way out as it seems to be today. Now, you've done me a huge favour because you have made me discover that the issue does not occur when calling the code from init. That is a much better workaround the issue in the meantime. Thank you Kevin! :+1:
Kevin Phillips
@phillipskevin
Jun 14 2016 14:39
you’re welcome
I’m glad that works
like you said, mustache is not used so much anymore
Fred Daoud
@foxdonut
Jun 14 2016 14:39
this code goes back to canjs 1.0.7 or so
Kevin Phillips
@phillipskevin
Jun 14 2016 14:40
you can still submit an issue if you want, and someone can maybe give you pointers on how to fix the issue
but it might be up to you to fix it if you really want a fix
Fred Daoud
@foxdonut
Jun 14 2016 14:40
yeah, I understand. at least the workaround is quite sensible.
Kevin Phillips
@phillipskevin
Jun 14 2016 14:40
ok good
Fred Daoud
@foxdonut
Jun 14 2016 14:40
I think I'll open the issue if only to document it, in case anyone else comes across something similar. it was quite difficult to figure out what was going on.
Kevin Phillips
@phillipskevin
Jun 14 2016 14:41
yeah, that’s totally cool
or you can submit a forum post: http://forums.donejs.com/c/canjs
Fred Daoud
@foxdonut
Jun 14 2016 14:42
I mean you call el.html("ABCD") and right after you call el.html() and it gives you back "AC" and you're like waaat? :confounded:
Kevin Phillips
@phillipskevin
Jun 14 2016 14:43
yeah, super confusing
Fred Daoud
@foxdonut
Jun 14 2016 14:43
not sure which (of github issue or forum post) would be most useful to the community?
Kevin Phillips
@phillipskevin
Jun 14 2016 14:48
hard to say
it’s up to you I guess
Fred Daoud
@foxdonut
Jun 14 2016 15:05
ok. thanks again, I appreciate it.
Kevin Phillips
@phillipskevin
Jun 14 2016 15:06
you’re welcome
Fred Daoud
@foxdonut
Jun 14 2016 15:20
canjs/canjs#2417
Kevin Phillips
@phillipskevin
Jun 14 2016 15:40
:thumbsup:
Thomas Sieverding
@Bajix
Jun 14 2016 19:20
This message was deleted
This message was deleted
Thomas Sieverding
@Bajix
Jun 14 2016 22:38
@justinbmeyer I’m running into some issues w/ how can-connect adds models to the the store
Previously you could do something like User.model({ _id: 1 }) === User.model({ _id: 1 })
That no longer works
However if I do findOne, they’ll both be the same instance
Was there a change in how the instance store is supposed to work, or should I create an issue for that?
Thomas Sieverding
@Bajix
Jun 14 2016 22:47
var superMap = require('can-connect/can/super-map/'),
  Model = require('can-connect/can/model/'),
  tag = require('can-connect/can/tag/');

require('can/map/define/');

/**
 * @add models/user
 */
var User = Model.extend({}, {
  define: {

  }
});

User.List = Model.List.extend({
  Map: User
}, {});

var connection = superMap({
  url: '/users',
  idProp: '_id',
  Map: User,
  List: User.List,
  name: 'user'
});

tag('user-model', connection);

exports.User = User;

-----------------

var assert = require('chai').assert,
  User = require('./user').User;

require('steal-mocha');

describe('User Model', function() {
  it('User store', function() {
    assert.equal(User.model({ _id: 999 }), User.model({ _id: 999 }));
  });
});
Justin Meyer
@justinbmeyer
Jun 14 2016 22:47
there is no more .model function
Thomas Sieverding
@Bajix
Jun 14 2016 22:47
There is in can-connect 0.5.5
Justin Meyer
@justinbmeyer
Jun 14 2016 22:48
not with superMap afaik
defines no model function
those are the static methods added by can-connect/can/map
anyhoo ... the connection itself should have an instanceStore property
Justin Meyer
@justinbmeyer
Jun 14 2016 22:50
the API of an instance store isn't documented, but it's connection.instanceStore.get
that's not part of superMap
oh, I noticed your code
it shouldn't be doing:
var User = Model.extend({}, {
  define: {

  }
});
you should extend can.Map, not can.Model
Thomas Sieverding
@Bajix
Jun 14 2016 22:51
can-connect/can/map/?
Justin Meyer
@justinbmeyer
Jun 14 2016 22:51
require('can-connect/can/model/') is only for legacy
Thomas Sieverding
@Bajix
Jun 14 2016 22:51
I see
That’s actually how I had it originally
Thomas Sieverding
@Bajix
Jun 14 2016 22:53
Btw, the findOne promise doesn’t chain w/ can.when
The callback returns a promise
Justin Meyer
@justinbmeyer
Jun 14 2016 22:54
yes, everything uses A+ promises
it's not a 100% compat fallback
just enough to pass the tests
Thomas Sieverding
@Bajix
Jun 14 2016 22:55
I see
So substituting jQuery 3.0 should fix that
Justin Meyer
@justinbmeyer
Jun 14 2016 22:55
Or using Promise.all
Thomas Sieverding
@Bajix
Jun 14 2016 22:56
Yes that too
So should new User({ _id: 1 }) === new User({ _id: 1 }) work?
Justin Meyer
@justinbmeyer
Jun 14 2016 22:56
that will not work
Thomas Sieverding
@Bajix
Jun 14 2016 22:58
Welp
User.model already hooks up to the connection store
How would I make that test pass?
Justin Meyer
@justinbmeyer
Jun 14 2016 22:59
I don't know what you mean by hooks up to the connection store
Thomas Sieverding
@Bajix
Jun 14 2016 22:59
model: function(raw){
  var args = makeArray(arguments);
  args[0] = this.connection.parseInstanceData.apply(this.connection, arguments);
  var instance = this.connection.hydrateInstance.apply(this.connection, arguments);
  return instance;
}
Justin Meyer
@justinbmeyer
Jun 14 2016 22:59
you shouldn't be using .model with superMap
Thomas Sieverding
@Bajix
Jun 14 2016 23:00
Ok but if I’m using superMap w/ a can-connection/can/map/map, how do I get the behavior that can.Model.model used to provide
Justin Meyer
@justinbmeyer
Jun 14 2016 23:00
as you shouldn't be using can-connect/can/model and superMap together on one type
use the instanceStore on the connection
Thomas Sieverding
@Bajix
Jun 14 2016 23:03
What method?
Justin Meyer
@justinbmeyer
Jun 14 2016 23:03
.get
Thomas Sieverding
@Bajix
Jun 14 2016 23:04
So there’s no convenience method that’s equivalent to what can.Model.model was?
Justin Meyer
@justinbmeyer
Jun 14 2016 23:04
there is not
Thomas Sieverding
@Bajix
Jun 14 2016 23:05
Is that a planned feature?
Justin Meyer
@justinbmeyer
Jun 14 2016 23:06
nope, .model shouldn't be used really .. it's indeterminate
Thomas Sieverding
@Bajix
Jun 14 2016 23:07
So for something like a websocket updater, just hook that up using instanceStore setters?
if you haven't, you should checkout the DoneJS chat or PMO guide
they both show how to deal with real time
Thomas Sieverding
@Bajix
Jun 14 2016 23:08
Ok cool, I’ll check that out
I had assumed can-connect was more similiar to can.Model.model than it is
Thomas Sieverding
@Bajix
Jun 14 2016 23:11
Why does the example differentiate between creation and updating?
Thanks for your help mate!
Justin Meyer
@justinbmeyer
Jun 14 2016 23:13
the same could be said for deletion and updating
a create means that instance should be added to lists
update means added or removed
delete means removed
also, we fire "created" events on instances when they are created
it's a useful differentiator for many interfaces
Thomas Sieverding
@Bajix
Jun 14 2016 23:14
Well, I mainly say that because the socket connection doesn’t necessarily need to know if it’s new or not, and what’s relevant is whether or not if it’s newly added to the store
Previously I had done this by having an init function that distpatched a newInstance event on my constructor
Would calling updateInstance on an instance that’s not in the store have any detrimental effect?
Does updateInstance upsert?
Justin Meyer
@justinbmeyer
Jun 14 2016 23:40
I think you're thinking only about instance updates
not list updates
where you have a list of items and you want an instance to appear in that list
yes, calling update will work
no, calling updateInstance on an item not in the store is totally fine
Thomas Sieverding
@Bajix
Jun 14 2016 23:46
Upserting would work for lists too
Simply if it’s not in the store, and you’re calling updateInstance, then emit a newInstance event or something similar