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

Angular component inside Vue component/template #79

Closed
arcadeJHS opened this issue Feb 4, 2019 · 11 comments
Closed

Angular component inside Vue component/template #79

arcadeJHS opened this issue Feb 4, 2019 · 11 comments

Comments

@arcadeJHS
Copy link

Hi, and thank you for your work!
I am trying to migrate a huge angular 1.x app into vue. I was wondering: is it possible to include an angular component into vue code?
I would like to re-use an existing angular component inside code refactored through Vue/ngVue, because I cannot simply rewrite it at the moment.
Let's say I am rewriting the "routing wrapper" of my application, but still, as the component loaded for a given route, I would like to inject the old angular code.

Something like:

<old-angular-app>
    <ng-vue-component>
        <old-existing-angular-component />
    </ng-vue-component>
</old-angular-app>

But it does not work, it gives a vue warn on unregistered component, which, I guess, is the right behaviour of the framework.
I know that maybe ngVue was intended to include vue components into angular, and not the contrary.
But I was wondering if it's possible to fix that in some way.

@jaredmcateer
Copy link
Member

jaredmcateer commented Feb 4, 2019

You can use the slot element in the vue template, however, the implementation is buggy and it seems like they are considering deprecating it.

I am also in the same boat as you, we're trying to migrate our angular app to vue and having the ability to have angular directives/components within a vue component is necessary.

I've found that you cannot have any whitespace between your vue component tags and the slot content. Your angular code cannot have any translcudes and there are some other buggy behaviours that I'm trying to work around atm.

E.g., Your example would have to be written as:

<old-angular-app>
    <ng-vue-component><old-existing-angular-component /></ng-vue-component>
</old-angular-app>

@arcadeJHS
Copy link
Author

Thank you for the suggestion @jaredmcateer!
I've found the buggy implementation mentioned in the issue #57.
At this point I am not sure if following this way (trying slots) it's a "good" choice... but still, as you, I have the necessity to keep angular code inside vue while migrating.

@nicolaspayot
Copy link
Member

I'm sorry but as you said, ngVue was not designed to allow AngularJS components to be rendered inside VueJS components. We've tried to add slots but it doesn't work in multiple situations: #66, due to the difference of rendering mechanism between AngularJS and Vue components.

However, you could compile an AngularJS component template within mounted() hook for example, inside your Vue component, and add the compiled element to the current element (this.$el):

mounted() {
    const template = `<custom-ng-tag foo="$ctrl.foo"></custom-ng-tag>`;

    const bindings = { foo: this.foo };

    const scope = angular.extend($rootScope.$new(), { $ctrl: bindings });
    const element = $compile(template)(scope);

    this.$el.append(element[0]);
}

This should kinda work but this is very experimental, imho. I would advise not to use it in production 😅

@arcadeJHS
Copy link
Author

Thank you @nicolaspayot!
I will experiment a little bit... as I said, I would prefer to preserve part on the existing angular code in a new Vue wrapper, and my main concern is how to handle the $scope in the existing angular code (which is quite pervasive and entangled into the application... ugly as it was...)!

@arcadeJHS
Copy link
Author

arcadeJHS commented Feb 6, 2019

@nicolaspayot: I am sorry, but I have a couple of (maybe stupid) question!

  1. It seems to me that using an angular component through slot seems to work in a "normal" template, but does not work when loading a component via vue-router. Is it right?

  2. In your example here above, how are you using $rootScope (and $compile)? It seems you are using it as a global object, but that should not be available there. Anyway, so far I got it working with a slightly different version:

mounted() {
    const el = angular.element(this.$el);
    el.injector().invoke(['$compile', '$rootScope', function($compile, $rootScope) {
        const scope = angular.extend($rootScope.$new(), {});
        $compile(el)(scope);
    }]);
}

Well... working... kind of... :-P

@arcadeJHS
Copy link
Author

I've come to this "AngularComponent.vue" component:

<template>
	<div></div>
</template>

<script>
export default {
	name: "AngularComponent",
	props: ['component'],
	mounted () {
		const el = angular.element(this.$el);
		const componentTemplate = this.component.template;
		const componentCtrl = this.component.$ctrl;

		el.injector().invoke(['$compile', '$rootScope', function($compile, $rootScope) {
			const scope = angular.extend($rootScope.$new(), {$ctrl: componentCtrl});
			el.append($compile(componentTemplate)(scope));
		}]);
	}
};
</script>

Inside a Vue component, to include an Angular component, I use it in this way:

<template>
	<div>
		<angular-component :component="angularComponent"></angular-component>
		<div>Vue template</div>
	</div>
</template>

<script>
import AngularComponent from './components/AngularComponent';

export default {
	name: "AngularInsideVue",
	components: { AngularComponent },
	data() {
		return {
			angularComponent: {
				template: '<example-component some-param="$ctrl.someParam"></example-component>',
				$ctrl: { someParam: 'Hello from Angular!' }
			}
		};
	}
};
</script>

Still I need to test it with more complex angular components, bindings, and updates, but it seems to work.

@Jvogel-Amplify
Copy link

@arcadeJHS Did you ever get this working with bindings, updates, etc...? I have a similar use case as you

@arcadeJHS
Copy link
Author

arcadeJHS commented Jul 25, 2019

@Jvogel-Amplify Well, I guess a sort of! :)
If you are interested in more details, I wrote on Medium a detailed review of that titled "Migrating an Angular 1.x app to Vue 2.x".

@arcadeJHS
Copy link
Author

arcadeJHS commented Jul 25, 2019

@Jvogel-Amplify ... which you can for sure read (together with code examples) on my github: https://github.com/arcadeJHS/AngularVueIntegration.

Hope it helps!

@Jvogel-Amplify
Copy link

This is a great guide thank you for documenting all of this! I am considering migrating an angular 1.x app to Vue so this will be a big help.

@arcadeJHS
Copy link
Author

@Jvogel-Amplify: no problem, thank you for reading! :-)
That, for sure, is my point of view... but I hope it helps.

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

4 participants