Connect nested components #179
Comments
It should be noted that when you nest components like this, these I'm not sure if you are particularly trying to compose your application this way, but logically you probably want |
Hi Evan, Yes, it makes sense. When you say to pass the children in the data array, you're suggesting to first create the child element(s) programatically into a variable and then pass it in the constructor of the parent element? To give you some context, I'm trying to create a collection of UI elements, to build up my application, and instead of creating large components, I was hoping to be able to divide one UI element in smaller reusable elements that I could then link together. And in some cases the child elements, need to be accessed by the parent or need to pass events to the parent. It would be nice if I could use custom tags for that, instead of passing raw elements in the data array. That would make building the interface a lot more flexible. I've built a system like this in Angular before, and was planning to release a similar UI collection for VueJS. |
Okay, so as of now transcluded components (components inserted as content) are available to the host component in an array as |
Thanks! I'll be playing around with it a bit more this week. If you like, I can keep you posted when I run into other issues or with a suggestion for a public API for these interactions based on my experience. |
Great! Yes please keep me updated :) |
I am thinking maybe we should add an option so that components can basically opt-in to "compile the content in its own scope". (kinda like Angular's Alternatively we can make it an attribute flag in the template similar to |
Actually in my tests so far, using So far this works as expected, it just feels hacky. I think there are a few options:
I should have a working example finished tomorrow morning that illustrates my use case better. |
I've put up an example of a tabpanel component, that illustrates the concept of connecting parent and child components to create a single UI element. Please note it's a quick example, I'm planning to work on a set of more solid components in the coming period. https://github.com/michielvandergeest/vueUI As you can see I pull in the I thought of another way to make this work prettier: Would it be an idea to have the child automatically call some kind of "register" method on the parent after it has been created? The register method on the parent would be optional. If the developer needs access to children, she is free to add the method to the parent component and add whatever kind of functionality to register the child as needed. Example:
One other thing that is a bit ugly in my current implementation is the direct use of What do you think? |
Thanks! The implementation helps me a lot in understanding what the needs of such components are. The current implementation looks find to me, the only thing I want to mention is that you should not bind to component instances directly as data (as in |
Thanks for the feedback! I'm working on some additional functionality to the component and run into an issue with that. I'm wondering how I would be able to create / instantiate a component programatically and insert it into a specific point in the DOM (through a v-el="targetElement" reference for example). I'm trying something like:
But this doesn't seem to work very well. The ChildComponent is created (created-callback is called), but it isn't being compiled / inserted into the DOM (the lifecycle stops before the beforeCompiled callback). Also it gives an error "Uncaught TypeError: Cannot read property '__v_trans' of null" Being able to create, compile and insert Vue Components on the fly through JS would really be very useful in creating a flexible component structure. Is this possible now within Vue? |
You need to give it an element or call $mount: http://vuejs.org/api/
|
Yeah, I had tried to pass the el option, but it gave some unexpected results. I think by now I've figured out what goes wrong. Or better, how it works different than I expected. When you pass an element to the new component instance, it replaces all the content inside that element with the compiled template of the component (even when replace is set to false in the component, by the way). I guess this makes sense when you parse a custom tag in the DOM (like v-child). But in my case I'd actually like to append the newly create element to the container element. I think it would be enough if we could just add a Check this CodePen for an illustrative example of how it replaces instead of appending: http://codepen.io/pensbymichiel/pen/rVwzbr |
Very interesting! |
The Any HTML inside the container node is considered parent content. If you don't provide a In general, working with the imperative component API requires a lot of understanding of how the internal compilation works. Maybe taking a read of the source code will help. |
@michielvandergeest I've pushed some changes to how transcluded components work in the latest
<tabs>
<tab></tab>
</tabs> Here for each In addition, event dispatching/broadcasting will now work properly between transcluded and host components. I believe this change largely solves the issue. |
For <tabs>
<template v-repeat="3">
<tab></tab>
</template>
<tab id="last"></tab>
<tab v-repeat="3"></tab>
</tabs> new Vue({
el: "body",
components: {
tabs: {
name: "tabs"
},
tab: {
name: "tab",
ready: function () {
console.log(this.$parent);
}
}
}
}); Only the |
@TerenceZ in this case the |
You can indeed access the child component with "$children". |
Try |
No, this doesn't work either. |
@PaulKruijt: Yes. You're correct. $$ is for v-el, my bad. |
Geen probleem ;-) |
@PaulKruijt are you trying |
Yes, i am...
|
I thought
no? |
That works but then the ui-submit is in the scope of the APP. I want it to be in the ui-form scope. |
I have the same need like @PaulKruijt <vue-form>
<vue-text></vue-text>
<vue-select></vue-select>
</vue-form> Here the I suggest a tag just like |
Sorry for bumping this, but just curious if anything was done here? I just ran into this issue myself. Maybe I'm mis-using Vue. My example is nearly identical to the OP... ran into same issue. |
I would like to know a way for doing this too... |
same here |
Will this use case be supported by vue 1.0 and/or vue 2.0? I really would like to do this easily: <tabs>
<tab></tab>
<tab></tab>
<tab></tab>
</tabs> |
+1 for that |
Having a proper way to communicate between nested Custom Components is crucial when building reusable semantic UI components, the tabs example is a good one. |
You should check out the new |
That looks very promising. Thank you! |
I'm looking for a way to connect nested components together in VueJS, how to have a parent component be aware of it's children and visa versa. I'm not only looking for a way to pass attributes down from the parent to the children, but also how to pass information 'up' from the children to it's parent.
Imagine the following:
I have 2 components defined in VueJS. Parent and Child
Then consider the following html:
The idea now is that it will create a parent div, and 3 child divs. Which is does. But my issue is that the parent is not aware that it has children. Somehow I would like to 'register' each child in the parent (to make the list of children in the v-repeat for example). Or I would like to be able to call an event from the child on the parent, so the parent can administer how the other children react to an event on one of the children.
I know I can pass down parameters using v-with, but I'm stuck on the part of setting up a real communication between the child and the parent.
Any ideas on how to do something like this in VueJS?
The text was updated successfully, but these errors were encountered: