Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Doc: proper way of passing a component to a ionic controller #38

Closed
zwacky opened this issue Oct 3, 2018 · 9 comments
Closed

Doc: proper way of passing a component to a ionic controller #38

zwacky opened this issue Oct 3, 2018 · 9 comments
Assignees

Comments

@zwacky
Copy link
Contributor

zwacky commented Oct 3, 2018

Hey all, I've been playing around with the ionic controllers, to be specific with popoverController.

Since I'm new to vue—and I see that you can do things in more than just one way—I ended up with the following solution below. On my way there I had these problems:

  • didn't know exactly how to pass a vue component instead of a simple html template
  • this.$store was undefined in passed component
// this['$ionic'] vs this.$ionic because there are no typings and I haven't created some either 😅
this['$ionic'].popoverController
	.create({
		component: {
			parent: this,
			render(h) {
				return h(NavBarVolumeSliderPopover);
				// also possible to pass props with `h(component, { props: { … } })`
			},
		},
		translucent: true,
		event,
	})
	.then(modal => modal.present());

The important part for me was parent: this, which made access to this.$store and all vuex bindings (throgh vuex-classes) possible.

Is there a more vueful way for this? In the end I could add a proper way to the docs here.

I hope you don't mind if I start that possibly leads to improvment of the project by creating this issue—otherwise please direct me in the right direction where to discuss these questions

@michaeltintiuc
Copy link
Member

Thanks @zwacky , I don't mind this at all, github works for the time being, I will investigate this as well, but to save you time, try passing NavBarVolumeSliderPopover directly to component, that should work, as well as passing a lazy-loaded component with webpack, ie:

{
  component: () => import('path/to/component.vue'),
}

@zwacky
Copy link
Contributor Author

zwacky commented Oct 4, 2018

I tried that approach but didn't work with my component that used vuex. It didn't have access to this.$store and mapState (etc) didn't work out of the box.
I also saw you all using it in your ModusCreateOrg/beep app, which I studied quite a bit to understand how things are done 😅

That is when I tried the parent: this parameter, which included this.$state in my NavBarVolumeSliderPopover component.
As I mentioned before I'm new to vue and probably there might be a better solution to this.

@michaeltintiuc
Copy link
Member

michaeltintiuc commented Oct 4, 2018

It does feel weird, what about passing the component directly?

import NavBarVolumeSliderPopover from 'path/to/NavBarVolumeSliderPopover.vue'
...
this['$ionic'].popoverController
	.create({
		component: NavBarVolumeSliderPopover,
		translucent: true,
		event,
	})
	.then(modal => modal.present());

From what I can tell, the vuex plugin is not being instantiated properly for it, I'll do further investigations as well

@michaeltintiuc michaeltintiuc self-assigned this Oct 8, 2018
@michaeltintiuc
Copy link
Member

@zwacky if you could share your code, it could help debug a particular way of doing things :)

@zwacky
Copy link
Contributor Author

zwacky commented Oct 8, 2018

@michaeltintiuc
Copy link
Member

Hey @zwacky , first of all, thanks for this bug submission, it's really awesome that you caught this edge-case. I dug around your code and you basically have 3 options here, due to the fact how Vuex adds the $store property to Vue objects

TLDR; The issue is that when you pass a component to ionic-vue it creates a new controller from a Vue instance, even though it has all of the settings and plugins like $router etc, Vuex does things differently and for some reason requires a component to have a parent in order to function properly, below are some possible solutions:

  1. Pass parent to PopoverController like so:
		this['$ionic'].popoverController
			.create({
				component: NavBarVolumeSliderPopover,
                                componentProps: { parent: this },
				translucent: true,
				event,
			})
			.then(modal => modal.present());
  1. Pass the store to the component as a property:
                import store from '@/store';
                ...
		this['$ionic'].popoverController
			.create({
				component: NavBarVolumeSliderPopover,
                                componentProps: { store },
				translucent: true,
				event,
			})
			.then(modal => modal.present());
  1. Use events to hook the 2 components together, I believe this is more of a vuetiful approach, essentially you would emit an event from the popover that the parent would listen to, but in your case this would be a bit more complicated as the popover component does not share a parent with the volumeSlider component.

@michaeltintiuc
Copy link
Member

@zwacky on the same note, turns out all of the above are good options and not "hacks":
buefy/buefy#55

@SanderMuller
Copy link

Would it be an idea to make Ionic pass the parent by default?

I just encountered this problem, and it took me a while to find this issue

@michaeltintiuc
Copy link
Member

Not as far as I know, the plugin is being initialized way before you reach the call to ionic controllers. I've looked into it and there's no way for it to "know" which component to set as it's parent out of the box.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants