Comments (41)
Hello @arlair
I browsed through the source of the page you linked, and I didn't see any instances of cycle-scope-*
.
The way that isolate works, here in cycle-snabbdom (and the other dom drivers), is it defines 'boundaries'. So if you call isolate() around a component that will create a view, that contains a <div />
and n children, you will end up with a <div class="cycle-scope-1" />
. When using DOM.select('.something')
from within that component, it is actually calling DOM.select(".cycle-scope-1").select(".something")
. This is how isolation in the DOM drivers work currently.
Depending on how many times isolate()
itself is called, it will generate new 'ids'.
See: https://github.com/cyclejs/isolate/blob/master/src/index.js#L1-L5
So I see that you're using webpack, my guess (tell me if I'm wrong), is that you're using hot reloading. So one thing that will happen is while hot-reloading, without calling isolate.reset() in your hot-reloading configuration
import isolate from '@cycle/isolate'
const {sinks, sources} = run(main, drivers)
if (module.hot) {
module.hot.accept()
module.hot.dispose(() => {
sinks.dispose()
sources.dispose()
})
isolate.reset() // here
}
You will continue to accumulate the counter inside of @cycle/isolate, which is why you could end up with 16, 17, 18 instead of 1, 2, 3
from cycle-snabbdom.
Thanks for the reply @TylorS.
It is an interesting idea about the hot reloading, although the demo site I linked is generated with a build script that should use the staging webpack config and not the dev config. On my dev machine I had also turned off hot reloading as I don't think think it was doing anything useful for me and I was having some other issues.
When I inspect the radio element, or do a find in the "Elements" view in Chrome Developer Tools I see the following:
I had a debugger break in the code here:
https://github.com/eldarlabs/cycle-ui/blob/master/src/helpers/componentFactory.ts#L12
and could see isolate being called many times, but I only get 3 of the cycle-scopes output. I had been trying to figure out the isolate code in cycle/isolate and cycle-snabbdom, but my understanding is not there yet, ;) I figured it was meant to happen every time it was called, but was not sure if there was some smart logic to omit cycle-scopes if it felt it was not necessary.
I have also tried the following code:
in replace of the above as I mentioned in my initial post
if (params.props.isolate) {
if (typeof sources === 'undefined') {
factory = isolateLocal(factory);
} else {
factory = sources.isolate(factory);
}
}
from cycle-snabbdom.
I just noticed that the components that get the cycle-scope have an empty div. I took out the following on one component:
{ props: { className } },
to make it an empty div and now I get a cycle-scope. It seems passing a className props blats the cycle-scope.
from cycle-snabbdom.
This could be a bug in my isolation code! Do you think it possible for you to wrangle together a small test (or a sample I could make into a test) ?
from cycle-snabbdom.
Also, I'm working on using data-cycle-isolate='scope'
instead of using a className to begin with!
from cycle-snabbdom.
Is there a basic cycle-snabbdom example repo somewhere I could fork?
from cycle-snabbdom.
Not that I know of, though you can use this as your starting point
http://esnextb.in/?gist=20a8535207697afa14eb7ee960db94d7
from cycle-snabbdom.
@TylorS Okay, try this out:
http://esnextb.in/?gist=29991688d608ddbadbc07706b5c77f86
from cycle-snabbdom.
Thanks @arlair - I in fact can reproduce using that. An interesting bit is if you use the selector instead of props, it works as you'd expect. I'm going to assume that this is an issue with cycle-snabbdom until I can investigate further.
http://esnextb.in/?gist=d374c0dcfdcd322167671bd6dfbdd4a3
from cycle-snabbdom.
Ahh, interesting. I use https://github.com/JedWatson/classnames in my components to create a varying number of classes. I tend to use the props version so I don't need to modify the selector version to include a '.' and formatting it to fit the selector format.
I guess there isn't much point fixing this if it will be replaced with the data-* isolation, but having a test that covers the different options might be useful.
from cycle-snabbdom.
@arlair Interestingly, this may not be cycle-snabbdom bug per se. http://esnextb.in/?gist=d374c0dcfdcd322167671bd6dfbdd4a3
The props
className overrides the usage of one by the selector. The DOM drivers use the selector to append the className to the vnode currently. So it seems that the 2 simply cannot coexist :(
from cycle-snabbdom.
Very interesting. A strange case. I remember considering a while back about removing support for selector in my components as being able to define it in two places is a bit confusing and partly because it made the overloading TypeScript method more complex. Overloading optional parameters in TypeScript is not very nice to implement :(
from cycle-snabbdom.
<-- secretly not a TypeScript fan
Yeah, working with TypeScript can be a pain when you begin to do anything remotely complex.
from cycle-snabbdom.
Haha, I'm not a fan of JavaScript ;). Unfortunately, TypeScript has to compile to JavaScript underneath which limits some of the things it can do. Optional parameters are horrible in TypeScript because they are horrible in JavaScript ;)
I find adding types and interfaces highlight issues in existing code bases and reduces bugs as I write. I also find it easier to understand code the code with types. However, I can understand why people can find them tedious, but I think they pay you back in the long term :).
from cycle-snabbdom.
Don't get me wrong, I love types, and would love having a strongly-typed language.
I'd love to use Elm (or something similar), but I'd miss Cycle too much!
from cycle-snabbdom.
Thank you for opening this today, its made me actually do things 👍
from cycle-snabbdom.
from cycle-snabbdom.
I was feeling bad as I thought you should have been looking around Copenhagen.
I have no cycle-scopes after trying the branch, although my intents all seem broken as well ;). I will have to check out what is happening.
from cycle-snabbdom.
Wonderful haha. I need to try and test them locally. I haven't yet, just have all the tests working currently.
from cycle-snabbdom.
http://codepen.io/TylorS/pen/mPjJGX?editors=0010
Really basic, but seems to be working for me here. Will try something better.
from cycle-snabbdom.
More of a perf test, but http://codepen.io/TylorS/pen/LNBVvL?editors=0010
from cycle-snabbdom.
Yeah, I get this counter code working in the pen:
http://codepen.io/rationaldev/pen/oxMjgo?editors=0010
I seem to have some issues with some similar code in my own project. I'm trying to cut it down to see where it is going wrong.
from cycle-snabbdom.
I'm trying to reproduce :)
Let me know if you can share anything that I can debug on!
from cycle-snabbdom.
Well I expect my own issue might be related to my scoping never having worked in the first place ;) I'm still a little confused as to how isolation works.
If I have some code like this:
const action$ = $.merge(
DOM.select('.counter').select('.decrement').events('click').map( (ev: any) => -1),
DOM.select('.increment').events('click').map( (ev: any) => +1)
);
let count$ = action$.startWith(0).scan((x: any, y: any) => x + y);
return {
DOM: count$.map(count =>
div('.counter', [
Button(sources, { isolate: true, className: 'decrement', label: 'Decrement' }).DOM,
Button(sources, { isolate: true, className: 'increment', label: 'Increment' }).DOM,
p('Counter: ' + count)
])
)
};
How can I target a Button component if it is isolated. Do I need to go down the tree at each level by classname like:
DOM.select('.counter').select('.decrement').events('click').map( (ev: any) => -1),
or can I get straight to what I want with:
DOM.select('.increment').events('click').map( (ev: any) => +1)
from cycle-snabbdom.
I tried putting the buttons into their own variables, but that doesn't help:
const incrementButton = Button(sources, { isolate: true, className: 'increment', label: 'Increment' });
If I make isolate false on both buttons they work using either select method.
from cycle-snabbdom.
I can also get events on both isolated buttons with
DOM.select('.counter').events('click').map( (ev: any) => -1),
but I can't figure out how to target their events individually. I want them isolated so they don't interfere with each other.
from cycle-snabbdom.
Could you share the code for the Button and how isolation is being supplied?
from cycle-snabbdom.
Sure.
Button:
https://github.com/eldarlabs/cycle-ui/blob/master/src/button/Button.ts
Isolation is enabled from the props, but the default isolation for Button is true.
https://github.com/eldarlabs/cycle-ui/blob/master/src/helpers/componentFactory.ts#L12
from cycle-snabbdom.
Although I have actually changed the isolation code to pass the isolation function it in via the sources.
if (params.props.isolate) {
if (typeof sources === 'undefined') {
factory = isolateLocal(factory);
} else {
factory = sources.isolate(factory);
}
}
from cycle-snabbdom.
I don't see anything apparent to me at the moment as to why its not working for you.
from cycle-snabbdom.
http://codepen.io/TylorS/pen/MyBado?editors=0010
I'm still having no issues ATM
from cycle-snabbdom.
I changed it back to always use local isolate (ie, not passed through from sources and imported in the file, just in case it was being messed with by isolation of the sources) and now only the decrement button works, but not the increment even though they are using the same selection method of going down the vtree. I also had to call isolate on the whole Counter component or else neither button works.
DOM.select('.counter').select('.decrement').events('click').map( (ev: any) => -1),
DOM.select('.counter').select('.increment').events('click').map( (ev: any) => +1)
Oh, I was thinking I should make a pen to simplify it, but looks like you already have. I will have a play with what you just sent. Thanks.
from cycle-snabbdom.
http://codepen.io/TylorS/pen/wGxMvG?editors=0010
This example makes heavy use of isolate()
from cycle-snabbdom.
Ahh, you are passing the click$ out of the Button in your example. I had wondered the other week if that is the only way to get the events out of an isolated component. I hope not, as that would mean every isolated component would have to pass out every type of event it could provide for external consumption.
from cycle-snabbdom.
I think this shows what I was trying to do, but I'm not sure it is allowed with the current isolation library. It works if you take out the isolation on the buttons. I'm trying to achieve the buttons being isolated by default so they don't mess with each other or other components, but for their events to be available when I ask for them specifically from an ancestor.
http://codepen.io/rationaldev/pen/LNBGxv?editors=0010
from cycle-snabbdom.
Yeah so the isolation semantics in the DOM drivers currently (for better or worse), purposefully make sure that parents can not query inside of isolated components like that.
from cycle-snabbdom.
The way Cycle tries to do things, is to make things very explicit, so passing a click$ from an isolated component is very normal and encouraged. If you need/want to do things by assigning and querying classNames (which really is a form of isolation, perhaps more explicit) like that, there really is no need for isolate()
from cycle-snabbdom.
Ok, thanks for your patience getting me to this point :).
I'm not sure how that works for a generic UI library like I was trying to build where potentially many events are possible for a component, but they can't interplay with each other with their internal intents. It seems like I only want partial isolation ;). I'm a bit confused now, so I guess I'll have to mull over whether I can do what I was trying to achieve :) Cheers.
from cycle-snabbdom.
Ok, thanks for your patience getting me to this point :).
Certainly, my pleasure.
It seems like I only want partial isolation
There have been chats about changing the way that isolate() works.
I've had some chats today, and I've been thinking of something along the lines of making it opt-out-able (not a word).
Something like DOM.select('.whatever').events('click', {own: false})
Where it wouldn't filter out childrens events, but would likely default to true
still for backwards compatibility.
Then likewise, I think there would need to be a change to .observable
, I think something like
DOM.select('.something').elements({own: false})
where own
would true
by default yet again here.
from cycle-snabbdom.
Yes, I have followed a lot of the online chats, but it still confuses me ;)
I think what I envisaged is components don't extend outside themselves by default, which is what I was trying to achieve by defaulting isolate to true. But I still want to be able to explicitly communicate with other components without exporting the HTML specification from each component ;)
from cycle-snabbdom.
Another thing related to the original issue here - snabbdom/snabbdom#103 (comment)
from cycle-snabbdom.
Related Issues (13)
- Any progress on the 'dirty hack' in Index.js? HOT 13
- Access snabbdom-to-html modules when using makeHTMLDriver HOT 1
- snabbdom-to-html should be a hard dependency
- Observable of vtrees inside a regular vtree HOT 4
- Cannot find module 'snabbdom-to-html' when installing from NPM HOT 24
- Silent failures with v1.1 HOT 13
- parseTree not handling null vTree HOT 18
- not receiving blur or focus events HOT 2
- Root element is replaced HOT 5
- Empty hyperscript helpers return undefined HOT 10
- can not make cycle-snabbdom runable with xstream HOT 1
- v1.0.1 throwing errors with empty children arrays? HOT 8
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from cycle-snabbdom.