{"id":13452192,"url":"https://github.com/ngVue/ngVue","last_synced_at":"2025-03-23T19:33:49.896Z","repository":{"id":10398642,"uuid":"65618781","full_name":"ngVue/ngVue","owner":"ngVue","description":"Use Vue2 components in Angular 1.x","archived":false,"fork":false,"pushed_at":"2024-03-28T02:49:08.000Z","size":1116,"stargazers_count":301,"open_issues_count":11,"forks_count":67,"subscribers_count":8,"default_branch":"master","last_synced_at":"2025-03-08T23:42:58.725Z","etag":null,"topics":["angular","integration","ngvue","vue-components","vuejs"],"latest_commit_sha":null,"homepage":"","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/ngVue.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2016-08-13T13:33:28.000Z","updated_at":"2025-02-28T03:02:41.000Z","dependencies_parsed_at":"2022-08-08T03:00:06.191Z","dependency_job_id":"0d348883-7980-489b-845f-fa663805cbcd","html_url":"https://github.com/ngVue/ngVue","commit_stats":{"total_commits":208,"total_committers":14,"mean_commits":"14.857142857142858","dds":0.6538461538461539,"last_synced_commit":"a43403d62429562198e0a3fc8212d1f7bbd63893"},"previous_names":[],"tags_count":29,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ngVue%2FngVue","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ngVue%2FngVue/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ngVue%2FngVue/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ngVue%2FngVue/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ngVue","download_url":"https://codeload.github.com/ngVue/ngVue/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":245159150,"owners_count":20570331,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["angular","integration","ngvue","vue-components","vuejs"],"created_at":"2024-07-31T07:01:16.526Z","updated_at":"2025-03-23T19:33:49.505Z","avatar_url":"https://github.com/ngVue.png","language":"JavaScript","funding_links":[],"categories":["JavaScript"],"sub_categories":[],"readme":"# ngVue\n\n\u003cp align=\"center\"\u003e:warning: For Vue 3 support use ngVue3 :warning:\u003c/p\u003e\n\u003cp align=\"center\"\u003e\u003ca href=\"https://github.com/jaredmcateer/ngvue3\"\u003eGithub\u003c/a\u003e | \u003ca href=\"https://www.npmjs.com/package/@jaredmcateer/ngvue3\"\u003enpm\u003c/a\u003e\u003c/p\u003e\n\n[![Build status](https://api.travis-ci.org/ngVue/ngVue.svg)](https://travis-ci.org/ngVue/ngVue) [![JavaScript Style Guide](https://img.shields.io/badge/code%20style-standard-brightgreen.svg)](http://standardjs.com/) [![npm version](https://badge.fury.io/js/ngVue.svg)](https://badge.fury.io/js/ngVue) [![Monthly npm downloads](https://img.shields.io/npm/dm/ngVue.svg)](https://img.shields.io/npm/dm/ngVue.svg) [![code style: prettier](https://img.shields.io/badge/code_style-prettier-ff69b4.svg?style=flat-square)](https://github.com/prettier/prettier)\n\n[**VueJS**](https://vuejs.org/) is a library to build web interfaces with composable view components and reactive data binding. **ngVue**, inspired by [ngReact](https://github.com/ngReact/ngReact), is an Angular module that allows you to develop/use Vue components in AngularJS applications. ngVue can be used in the existing Angular applications and helps migrate the view parts of the application from Angular 1.x to Vue 2.\n\nThe motivation for this is similar to ngReact's:\n\n- The AngularJS application suffers from a performance bottleneck due to a huge amount of scope watchers on the page, but VueJS offers an amazing reactive data-binding mechanism and other optimizations\n- Instead of two-way data flow between controllers and views, VueJS defaults to a one-way, parent-to-child data flow between components which makes the application more predictable\n- VueJS offers a much easier way to compose the web interfaces, and you can take advantage of the functional reactive programming in VueJS 2. Angular directives introduce a high learning barrier, such as the compile and link function, and the directives are prone to get confused with the components\n- The VueJS community offers a component or a UI framework that you would like to try out\n- Too deep into an AngularJS application to move it away from the code but you would like to experiment with VueJS\n\n## Table of Contents\n\n- [ngVue](#ngvue)\n  - [Table of Contents](#table-of-contents)\n  - [Install](#install)\n  - [Usage](#usage)\n  - [Features](#features)\n    - [The vue-component directive](#the-vue-component-directive)\n      - [Handling events](#handling-events)\n    - [Handling HTML attributes](#handling-html-attributes)\n    - [The createVueComponent factory](#the-createvuecomponent-factory)\n    - [Composition API](#composition-api)\n  - [Caveats](#caveats)\n  - [Plugins](#plugins)\n  - [TODO](#todo)\n\n## Install\n\nvia npm:\n\n```\nnpm install ngVue\n```\n\n## Usage\n\n**ngVue** is a UMD module (known as Universal Module Definition), so it's CommonJS and AMD compatible, as well as supporting browser global variable definition.\n\nFirst of all, remember to load AngularJS 1.x, VueJS and ngVue:\n\n```html\n// load on the page with the `script` tag\n\u003cscript src=\"./node_modules/angular/angular.js\"\u003e\u003c/script\u003e\n\u003cscript src=\"./node_modules/vue/dist/vue.js\"\u003e\u003c/script\u003e\n\u003cscript src=\"./node_modules/ngVue/build/index.js\"\u003e\u003c/script\u003e\n```\n\nor ...\n\n```javascript\n// the CommonJS style\nconst ng = require('angular')\nconst vue = require('vue')\nrequire('ngVue')\n\n// the AMD style\nrequire(['angular', 'vue', 'ngVue'], function(ng, Vue) {\n})\n\n// the ECMAScript module style\nimport angular from 'angular'\nimport vue from 'vue'\nimport 'ngVue'\n```\n\nand then require `ngVue` as a dependency for the Angular app:\n\n```javascript\nangular.module('yourApp', ['ngVue'])\n```\n\n## Features\n\n**ngVue** is composed of a directive `vue-component`, a factory `createVueComponent` and a directive helper `v-directives`. It also provides some plugins for enhancement.\n\n- `vue-component` is a directive that delegates data to a Vue component so VueJS can compile it with the corresponding nodes\n- `createVueComponent` is a factory that converts a Vue component into a `vue-component` directive\n\n**ngVue** does support VueJS directives but currently they only work with a Vue component in AngularJS templates.\n\n- `v-directives` is a directive to apply the vue directives to the vue components\n\n```html\n\u003c!-- This won't work --\u003e\n\u003cdiv v-directives=\"hello\"\u003e\u003c/div\u003e\n\n\u003c!-- But this will work ... --\u003e\n\u003cvue-component name=\"HelloComponent\" v-directives=\"hello\"\u003e\u003c/vue-component\u003e\n\u003c!-- Or ... --\u003e\n\u003chello-component v-directives=\"hello\"\u003e\u003c/hello-component\u003e\n```\n\n### The vue-component directive\n\nThe `vue-component` directive wraps the vue component into an angular directive so that the vue component can be created and initialized while the angular is compiling the templates.\n\nAt first an **Angular controller** needs creating to declare the view data like this:\n\n```javascript\nconst app = angular.module('vue.components', ['ngVue'])\n  .controller('MainController', function () {\n    this.person = {\n      firstName: 'The',\n      lastName: 'World'\n    }\n  })\n```\n\nThen declare **a Vue component** like this:\n\n```javascript\nconst VComponent = Vue.component('hello-component', {\n  props: {\n    firstName: String,\n    lastName: String\n  },\n  render (h) {\n    return (\n      \u003cspan\u003eHi, { this.firstName } { this.lastName }\u003c/span\u003e\n    )\n  }\n})\n```\n\nIn the end, **register the Vue component** to the Angular module with `value` method like this:\n\n```javascript\napp.value('HelloComponent', VComponent);\n```\n\nNow you can use `hello-component` in Angular templates:\n\n```html\n\u003cbody ng-app=\"vue.components\"\u003e\n  \u003cdiv class=\"hello-card\"\n       ng-controller=\"MainController as ctrl\"\u003e\n    \u003cvue-component name=\"HelloComponent\"\n                   v-props=\"ctrl.person\"\n                   watch-depth=\"value\" /\u003e\n  \u003c/div\u003e\n\u003c/body\u003e\n```\n\nThe `vue-component` directive provides three main attributes:\n\n- `name` attribute checks for Angular injectable of that name\n\n- `v-props` attribute is a string expression evaluated to an object as the data exposed to Vue component\n\n- `v-props-*` attribute allows you to name the partial data extracted from the angular scope. `vue-component` wraps them into a new object and pass it to the Vue component. For example `props-first-name` and `props-last-name` will create two properties `firstName` and `lastName` in a new object as the component data\n\n```html\n\u003cvue-component v-props=\"ctrl.person\" /\u003e\n\u003c!-- equals to --\u003e\n\u003cvue-component v-props-first-name=\"ctrl.person.firstName\" v-props-last-name=\"ctrl.person.lastName\" /\u003e\n```\n\n- `watch-depth` attribute indicates which watch strategy AngularJS will use to detect the changes on the scope objects. The possible values as follows:\n\n| value      | description                                                                                                                                                                          |\n| ---------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |\n| reference  | *(default)* watches the object reference                                                                                                                                             |\n| collection | *(rarely used)* same as angular `$watchCollection`, shallow watches the properties of the object: for arrays, it watches the array items; for object maps, it watches the properties |\n| value      | *(rarely used)* deep watches every property inside the object                                                                                                                        |\n\n**NOTES**\n\n- `watch-depth` cannot propagate all the changes on the scope objects to VueJS due to the limitation of the reactivity system, but you can read about several solutions in [Caveats](docs/caveats.md#limitations--solutions).\n- The `collection` strategy and the `value` strategy are rarely used. The scope object will be converted into a reactive object by VueJS and so any changes on the reactive scope object will trigger the view updates.\n- The `value` strategy is **not recommended** because it causes a heavy computation. To detect the change, Angular copies the entire object and traverses every property insides in each digest cycle.\n\n#### Handling events\n\nEvents can be handled from Vue to AngularJS components by binding functions references as `v-on-*`:\n\n```javascript\napp.controller('MainController', function ($scope) {\n  this.handleHelloEvent = function (greetings) {\n    console.log(greetings); // \"Hello, World!\"\n  }\n})\n```\n\n```html\n\u003cvue-component v-on-hello-world=\"ctrl.handleHelloEvent\"\u003e\u003c/vue-component\u003e\n```\n\n```javascript\nconst VComponent = Vue.component('hello-component', {\n  methods: {\n    helloFromVue() {\n      this.$emit('hello-world', 'Hello, World!');\n    }\n  },\n  render (h) {\n    return (\n      \u003cbutton onClick={this.helloFromVue}\u003e\u003c/button\u003e\n    )\n  }\n})\n```\n\nEvents name in `$emit` function should be using kebab-case syntax.\n\n### Handling HTML attributes\n\nJust like regular Vue components, you can pass HTML attributes from the parent Angular component to your Vue component.\nThe parent's `class` and `style` attributes will be merged with the corresponding Vue component attributes, while others will be passed down unless they conflict with attributes in the Vue component's own template.\nKeep in mind that when you pass down literal strings for anything other than `class` and `style` attributes, they must be surrounded by quotes, e.g. `data-value=\"'enabled'\"`.\n\n```javascript\nangular.module(\"app\")\n  .directive(\"myCustomButton\", createVueComponent =\u003e {\n    return createVueComponent(Vue.component(\"MyCustomButton\", MyCustomButton))\n  })\n```\n\n```html\n\u003cmy-custom-button\n  disabled=\"ctrl.isDisabled\"\n  class=\"excellent\"\n  tabindex=\"3\"\n  type=\"'submit'\"\n  v-props-button-text=\"'Click me'\" /\u003e\n```\n\n```vue\n\u003ctemplate\u003e\n\u003c!-- tabindex, type, class, and disabled will appear on the button element --\u003e\n\u003cbutton\u003e\n  {{ buttonText }}\n\u003c/button\u003e\n\u003c/template\u003e\n\n\u003cscript\u003e\nexport default {\n  name: \"my-custom-button\",\n  props: [\"buttonText\"],\n}\n\u003c/script\u003e\n```\n\nNote that using `inheritAttrs: false` and binding `$attrs` to another element is also supported:\n\n```vue\n\u003ctemplate\u003e\n\u003cdiv\u003e\n  \u003c!-- tabindex and type should appear on the button element instead of the parent div --\u003e\n  \u003cbutton v-bind=\"$attrs\"\u003e\n    {{ buttonText }}\n  \u003c/button\u003e\n  \u003cspan\u003eOther elements\u003c/span\u003e\n\u003c/div\u003e\n\u003c/template\u003e\n\n\u003cscript\u003e\nexport default {\n  inheritAttrs: false,\n  name: \"my-custom-button\",\n  props: [\"buttonText\"],\n}\n\u003c/script\u003e\n```\n\n### The createVueComponent factory\n\nThe `createVueComponent` factory creates a reusable Angular directive which is bound to a specific Vue component.\n\nFor example, with the `vue-component` directive as mentioned above, you have to register each Vue component with a string name and then write `\u003cvue-component name=\"TheRegisteredName\"\u003e\u003c/vue-component\u003e` repeatedly. With this `createVueComponent` factory, however, you can create `\u003cname-of-vue-component\u003e\u003c/name-of-vue-component\u003e` directives and simply apply the exported Vue components to them.\n\nThe factory returns a plain `$compile` options object which describes how to compile the Angular directive with VueJS, and it takes the Vue component as the first argument:\n\n```javascript\napp.directive('helloComponent', function (createVueComponent) {\n  return createVueComponent(VComponent)\n})\n```\n\nAlternatively, the name of the Vue component registered by `angular.value` can also be provided to the factory:\n\n```javascript\napp.directive('helloComponent', function (createVueComponent) {\n  return createVueComponent('HelloComponent')\n})\n```\n\n### Composition API\n\nThe [Vue 2 Composition API](https://github.com/vuejs/composition-api) plugin is supported with the usual [limitations](https://github.com/vuejs/composition-api#limitations), additionally the component **MUST** include a `setup` function, there isn't a good way to detect it otherwise.\n\n_Uses Composition API_\n\n```js\nexport default Vue.component('my-component', {\n  setup() {},\n  render(h) {\n    return (\u003cdiv\u003e\u003c/div\u003e)\n  }\n})\n```\n\n_Fall back to Options API_\n\n```js\nexport default Vue.component('my-component', {\n  render() {\n    return (\u003cdiv\u003e\u003c/div\u003e);\n  }\n});\n```\n\nYou don't necessarily need to use `Vue.component` when defining Composition API components but without a `setup` method ngVue will not be able to link it.\n\n_This works_\n\n```js\nexport default {\n  setup() {},\n  render(h) {\n    return (\u003cdiv\u003e\u003c/div\u003e)\n  }\n}\n```\n\n_This will break_\n\n```js\nexport default {\n  render(h) {\n    return (\u003cdiv\u003e\u003c/div\u003e)\n  }\n}\n```\n\n## Caveats\n\nngVue brings the reactivity system to the dirty checking mechanism and you should therefore understand how they work together and how to avoid some common gotchas. Please read more in the [Caveats](docs/caveats.md).\n\n## Plugins\n\nngVue is simple but flexible for enhancement. Please read more in the [Plugins](docs/plugins.md).\n\n## TODO\n\n- [x] vue components\n- [x] vue directives\n- [x] unit tests\n- [x] docs + simple examples\n- [x] ng filters in VueJS\n- [x] supports vuex\n- [ ] performance optimization\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FngVue%2FngVue","html_url":"https://awesome.ecosyste.ms/projects/github.com%2FngVue%2FngVue","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FngVue%2FngVue/lists"}