These are chat archives for ractivejs/ractive

15th
Jan 2019
Arnaud Dagnelies
@dagnelies
Jan 15 15:23
@kouts Look here: https://dagnelies.github.io/ractive-examples/ there are plenty of examples which may inspire you. I think especially the "movies 1-4" demos would be quite nice to build in a workshop since it produces something nice, real-life related, relatively easely. The first one being https://dagnelies.github.io/ractive-examples/demos/movies_1.html (it's a single page example)
@twisterxiz_gitlab No idea. But providing an online example to tweak, play around with, would make things easier in order to provide proper advice.
Brandon
@twisterxiz_gitlab
Jan 15 16:30
There's not really a way to make this an example, I'm walking through the debugger and watching how the expre
Chris Reeves
@evs-chris
Jan 15 16:57
@twisterxiz_gitlab it sounds like something is a little off somewhere, as it shouldn't recompute the world when one property changes
you can avoid the every keystroke issue by adding lazy=500 to the input that triggers the change, which will delay changing the bound data until at least 500ms happens after a keystroke
@kouts neat! I don't have any local dev groups, so I've not really thought about it. Most people have no idea what ractive is, so probably a quick see-how-easy-this-is, followed by a mile high overview of features, ending with a check out this feature that I think is really neat.
@twisterxiz_gitlab can you give us a short overview of your data and template?
I've got some very large complex templates, and the only time I cross the 100ms boundary for a render is when there's a ton of stuff being added to the page (tens of thousands of DOM nodes) or I have a giant list rendered with :nth-child selectors that do something whacky with forcing layout updates
Brandon
@twisterxiz_gitlab
Jan 15 18:11
Weird I didn't see that last message get cut off
but yeah I've done some more deep diving
in .8.15 there are a couple of methods such as ExpressionProxy getvalue and component update (fragment update) and section.update for the fragments as well
Our use of Ractive is actually light outside of get/set, pretty much all of our Components are non-isolated
e.g.
Ractive.components.grid = Ractive.extend({
template: "#grid"
});
so that's my first hunch
but really besides those components and a few decorators we really aren't integrated with ractive that heavily
most of our data model is using a es6 Proxies to intercept set calls so we also set them in racctive
and that's about it
In general what I'm seeing is that although this div might be 50 layers deep, the .bubble method eventually goes all the way to the top of the template div and then recalculates everything along that path
Brandon
@twisterxiz_gitlab
Jan 15 18:17
so the more I look at this, the more I believe it could be because the component isn't isolated and therefore the dirty checks always bubble to the top?
So for example that grid component might have a reference to "currentAccount" that is linked to say "accounts.3", and if anything inside that grid component updates, it bubbles to all components above it in the dom hiearchy so the template reevaluates all references for our css attribtues/etc

To be clear if we have components inside other components, for example (not using real syntax):

<dashboard>
... content ...
<grid />
</dashboard>

any update to the currentAccount model inside the grid component for a single property, let's say ractive.set("currentAccount.newPost") will update not only the reference inside the grid component but the entire page all the way up to dashboard and beyond although the only property set is referenced twice (once for the input field, once for the text duplication div)

here's an example of an edited mockup for the template
Brandon
@twisterxiz_gitlab
Jan 15 18:32
That's the duplicate template
is the input template
So any time the newPostTitle input gets changed not only does it reevaluate both these fragments, it also updates up the hierarchy to anything referencing <postCard> in their component, etc
@evs-chris I've done something similar manually with an observer intermediary property and setTimeout but that's good to know, however this seems to be a fundamental issue that I'm certain we'll struggle with future requirements
Oh also tagging @dagnelies
Chris Reeves
@evs-chris
Jan 15 19:05
nothing jumps out in the template
updates are supposed to bubble to the top, but fragments not flagged dirty shouldn't do anything on the subsequent update pass
it looks like a lot of computations in the template depend on currentAccount
updating that would cause lots of invalidation, if that's the case
you could try holding the data that's changing and only supposed to affect two chunks of template in a holding path like tmp.postTitle
Brandon
@twisterxiz_gitlab
Jan 15 19:13
So basically updating a path like currentAccount.posts.<variable> is expected to recalulate everything that references currentAccount and/or posts?
And there's no way to limit the blast range other than to create another keypath that isn't referenced in the template?
So it's no so much the fact that our components are not isolated as much as it is that we aren't using a different ractive path for storing a lot of these transient properties?
not*
Brandon
@twisterxiz_gitlab
Jan 15 19:20
It feels rather wrong to not encapsulate these properties, you're basically suggesting instead of accounts[3].posts.property to have accounts[3] and posts[3].property separately and then have a leaky abstraction for the accountId 3 for all my commonly updated template variables
and even worse for linked models I would have to do something like ractive.set("posts." + ractive.get("currentAccount").id + ".text", text)
instead of ractive.set("currentAccount.posts.text", text")
Brandon
@twisterxiz_gitlab
Jan 15 19:42
Also I have no idea how notifications work on here so repinging @evs-chris
Chris Reeves
@evs-chris
Jan 15 19:52
gitter sometimes notifies and sometimes doesn't
unfortunately
no, you can encapsulate your data, but if you have an expression that references currentAccount, then any time something in currentAccount changes, it's going to cause all of the expressions referencing it to recompute
of course I'm guessing a bit here
if you have something I can look at out of band, I could probably offer more insight
Brandon
@twisterxiz_gitlab
Jan 15 20:13
Well I guess what I'm pointing out that in our model, everything is bound to an account, so pretty much an update to anything will update all account references
so like we have account.cards, an array of cards iterated on the page including a card with type "postCard" that references the <postCard> template and points back to the accounts.posts object
so you're saying that accounts.posts.text that is referenced in the post card will affect anything that mentions account in the account.cards iterated templates
which is what I'm seeing, it makes sense
but I thought there would be a way to to indicate to ractive that a property change doesn't require all references up the keypath to reevaluate
our accounts also have a grid, that also has apps
so if those apps refer to currentAccount, it will reupdate any references in the app, other apps, the grid itself, and so on
@evs-chris
Chris Reeves
@evs-chris
Jan 15 20:17
it sounds like that's what's happening
Brandon
@twisterxiz_gitlab
Jan 15 20:18
sucks but not unmanagable I don't think
I think I can limit a lot of the leaky abstractions to those proxy objects I'm using for our pseudo magic mode
Chris Reeves
@evs-chris
Jan 15 20:18
do you have locking in the proxies?
Brandon
@twisterxiz_gitlab
Jan 15 20:19
No it's pretty much a straight passthrough
var thisGrid = new Proxy({}, {
    set : function(obj, prop, value){
        if(obj[prop] !== value){
            obj[prop] = value;
            if(created){
                ractive.set("accounts." + account.id + "." + type + "." + prop, value);
            }
        }
        return true;
    }
});
Chris Reeves
@evs-chris
Jan 15 20:21
I suppose that's kinda self-locking with the ident check on the value
Brandon
@twisterxiz_gitlab
Jan 15 20:21
But this is only called once, and in this situation isn't even invoked
because the path is two-way bound input -> dirty check -> render on page
not grid.property = true -> proxy ractive set -> dirty check -> render on page
Chris Reeves
@evs-chris
Jan 15 20:22
if you're not worried about tracking changes across non-current accounts, you could set the relevant objects from the current account as top-level data e.g. this.set('posts', currentAccount.posts), which will break the connection between currentAccount and posts in ractive to stop updating the world when posts changes
Brandon
@twisterxiz_gitlab
Jan 15 20:23
now that is something I was looking for
Chris Reeves
@evs-chris
Jan 15 20:23
then to sync everything back up when you're ready this.update('currentAccount')
Brandon
@twisterxiz_gitlab
Jan 15 20:23
yeah that's not the worst, I can basically hook into our setCurrentAccount method and then procedurally do that
honestly it might be best for us to completely decouple it
for all accounts that is, it's also less janky for our other developers
In general I'll keep in mind though that in general the deeper the path, the more updates will trigger
I didn't even think about it but a lot of our keypaths look like currentAccount.grid.apps.1.apps.2.apps.3 and so on
so I would imagine that's a huge optimization issue too, but we haven't really done any real time changes for that
Chris Reeves
@evs-chris
Jan 15 20:37
deep paths are only really an issue if you're using them both shallow and deep, as it seems you are with currentAccount being used a good bit
Brandon
@twisterxiz_gitlab
Jan 15 20:39
yeah good point
Anyway thanks again for the help, love the library and hope to one day be fortunate enough to get to do a new project with 1.0 haha