2
0
mirror of https://github.com/tenrok/vue-tribute.git synced 2026-06-23 10:50:35 +03:00

Merge pull request #2 from deckardai/master

Support reactive items. Separate options from items.
This commit is contained in:
Collin Henderson
2016-12-07 14:40:11 -05:00
committed by GitHub
6 changed files with 87 additions and 99 deletions
+22 -12
View File
@@ -23,25 +23,35 @@ $ npm install vue-tribute --save
import Vue from "vue"; import Vue from "vue";
import VueTribute from "vue-tribute"; import VueTribute from "vue-tribute";
Vue.use(VueTribute, options); Vue.use(VueTribute, globalOptions);
``` ```
> The `options` parameter is optional. > The `globalOptions` parameter is optional.
...and inside your template, bind a dynamic `values` parameter to some data: ...and inside your template, bind a dynamic `values` parameter to some data:
`<input type='text' :values='items' v-tribute />`
The `values` array should be an array of objects that contain a key and value like so:
``` ```
[ <input type='text'
{key: "Phil Heartman", value: "pheartman"}, v-tribute='tributeUsers'
{key: "Gordon Ramsey", value: "gramsey"} :tributeoptions='{ trigger:"#" }' />
]
``` ```
You can modify this structure using the built-in [Tribute options](https://github.com/zurb/tribute#a-collection). The value of `v-tribute` should be an array of objects that contain a `key` to search and a `value` to be inserted. We recommend using a Vue computed property to format your data like so:
```
computed: {
tributeUsers: function() {
return [
{key: "Phil Heartman", value: "pheartman"},
{key: "Gordon Ramsey", value: "gramsey"}
]
},
},
```
The `tributeoptions` attribute is optional. It is merged with `globalOptions` and takes precendence.
See the available options [here](https://github.com/zurb/tribute#a-collection).
## Events ## Events
@@ -49,4 +59,4 @@ Tribute broadcasts two events — a `tribute-replaced` event, and a `tribute-no-
## License ## License
MIT © [Collin Henderson](https://github.com/syropian) MIT © [Collin Henderson](https://github.com/syropian), [Aurélien Nicolas](https://github.com/deckardai)
+16 -26
View File
@@ -8,44 +8,34 @@ if (!Tribute) {
throw new Error("[vue-tribute] cannot locate tributejs"); throw new Error("[vue-tribute] cannot locate tributejs");
} }
exports.install = function (Vue, options) { exports.install = function (Vue, globalOptions) {
Vue.directive("tribute", { Vue.directive("tribute", {
params: ["values"], params: ["tributeoptions"],
tribute: null, tribute: null,
paramWatchers: {
values: function values(val, oldVal) { /** Create a Tribute instance for this element */
this.setValues(val);
}
},
bind: function bind() { bind: function bind() {
var _this = this; var _this = this;
// If it has a "values" property, it's actually a collection this.tribute = new Tribute(Object.assign({
if (this.params.values.hasOwnProperty("values")) { values: []
this.tribute = new Tribute({ }, globalOptions, this.params.tributeoptions));
collection: this.params.values
});
} else {
this.tribute = new Tribute(Object.assign({
values: this.params.values
}, options));
}
this.tribute.attach(this.el); this.tribute.attach(this.el);
this.el.addEventListener("tribute-replaced", function (e) { this.el.addEventListener("tribute-replaced", function (e) {
_this.vm.$emit("tribute-replaced"); _this.vm.$emit("tribute-replaced", e);
}); });
this.el.addEventListener("tribute-no-match", function (e) { this.el.addEventListener("tribute-no-match", function (e) {
_this.vm.$emit("tribute-no-match"); _this.vm.$emit("tribute-no-match", e);
}); });
}, },
setValues: function setValues(values) {
// If it has a "values" property, it's actually a collection
if (values.hasOwnProperty("values")) { /** Set the initial or updated items */
this.tribute.collection = values; update: function update(values) {
} else { this.tribute.append(0, values, /* replace= */true);
this.tribute.collection[0].values = values;
}
} }
}); });
}; };
+16 -26
View File
@@ -10,44 +10,34 @@
throw new Error("[vue-tribute] cannot locate tributejs"); throw new Error("[vue-tribute] cannot locate tributejs");
} }
exports.install = function (Vue, options) { exports.install = function (Vue, globalOptions) {
Vue.directive("tribute", { Vue.directive("tribute", {
params: ["values"], params: ["tributeoptions"],
tribute: null, tribute: null,
paramWatchers: {
values: function values(val, oldVal) { /** Create a Tribute instance for this element */
this.setValues(val);
}
},
bind: function bind() { bind: function bind() {
var _this = this; var _this = this;
// If it has a "values" property, it's actually a collection this.tribute = new Tribute(Object.assign({
if (this.params.values.hasOwnProperty("values")) { values: []
this.tribute = new Tribute({ }, globalOptions, this.params.tributeoptions));
collection: this.params.values
});
} else {
this.tribute = new Tribute(Object.assign({
values: this.params.values
}, options));
}
this.tribute.attach(this.el); this.tribute.attach(this.el);
this.el.addEventListener("tribute-replaced", function (e) { this.el.addEventListener("tribute-replaced", function (e) {
_this.vm.$emit("tribute-replaced"); _this.vm.$emit("tribute-replaced", e);
}); });
this.el.addEventListener("tribute-no-match", function (e) { this.el.addEventListener("tribute-no-match", function (e) {
_this.vm.$emit("tribute-no-match"); _this.vm.$emit("tribute-no-match", e);
}); });
}, },
setValues: function setValues(values) {
// If it has a "values" property, it's actually a collection
if (values.hasOwnProperty("values")) { /** Set the initial or updated items */
this.tribute.collection = values; update: function update(values) {
} else { this.tribute.append(0, values, /* replace= */true);
this.tribute.collection[0].values = values;
}
} }
}); });
}; };
+1 -1
View File
@@ -1,6 +1,6 @@
{ {
"name": "vue-tribute", "name": "vue-tribute",
"version": "0.1.3", "version": "0.2.0",
"description": "A Vue.js wrapper for Zurb's Tribute library for native @mentions", "description": "A Vue.js wrapper for Zurb's Tribute library for native @mentions",
"license": "MIT", "license": "MIT",
"repository": "syropian/vue-tribute", "repository": "syropian/vue-tribute",
+17 -28
View File
@@ -4,42 +4,31 @@ if (!Tribute) {
throw new Error("[vue-tribute] cannot locate tributejs") throw new Error("[vue-tribute] cannot locate tributejs")
} }
exports.install = function (Vue, options) { exports.install = function (Vue, globalOptions) {
Vue.directive("tribute", { Vue.directive("tribute", {
params: ["values"], params: ["tributeoptions"],
tribute: null, tribute: null,
paramWatchers: {
values (val, oldVal) { /** Create a Tribute instance for this element */
this.setValues(val) bind() {
} this.tribute = new Tribute(Object.assign({
}, values: [],
bind () { }, globalOptions, this.params.tributeoptions))
// If it has a "values" property, it's actually a collection
if (this.params.values.hasOwnProperty("values")) {
this.tribute = new Tribute({
collection: this.params.values
})
} else {
this.tribute = new Tribute(Object.assign({
values: this.params.values
}, options))
}
this.tribute.attach(this.el) this.tribute.attach(this.el)
this.el.addEventListener("tribute-replaced", e => { this.el.addEventListener("tribute-replaced", e => {
this.vm.$emit("tribute-replaced") this.vm.$emit("tribute-replaced", e)
}) })
this.el.addEventListener("tribute-no-match", e => { this.el.addEventListener("tribute-no-match", e => {
this.vm.$emit("tribute-no-match") this.vm.$emit("tribute-no-match", e)
}) })
}, },
setValues (values) {
// If it has a "values" property, it's actually a collection /** Set the initial or updated items */
if (values.hasOwnProperty("values")) { update(values) {
this.tribute.collection = values this.tribute.append(0, values, /* replace= */ true)
} else { },
this.tribute.collection[0].values = values
}
}
}) })
} }
+15 -6
View File
@@ -7,7 +7,10 @@ beforeEach(() => {
vm = new Vue({ vm = new Vue({
el: document.body, el: document.body,
replace: false, replace: false,
template: "<input type='text' :values='items' v-tribute />", template: `<input type='text'
v-tribute='items'
:tributeoptions='{trigger: "#"}'
/>`,
data(){ data(){
return { return {
items: [ items: [
@@ -27,8 +30,14 @@ describe("vue-tribute", () => {
expect(typeof vm.$options.directives["tribute"]).toEqual("object") expect(typeof vm.$options.directives["tribute"]).toEqual("object")
}) })
it("triggers the param watcher when the underlying model changes", (done) => { it("supports tribute options", () => {
spyOn(vm.$options.directives["tribute"].paramWatchers, "values").and.callThrough() expect(vm._directives[0].tribute.collection[0].trigger).toEqual("#")
})
it("updates the items when the underlying model changes", (done) => {
const directive = vm._directives[0]
expect(directive.tribute.collection[0].values).toEqual(vm.items)
const newItems = [ const newItems = [
{key: "Kerem Suer", value: "kerem"}, {key: "Kerem Suer", value: "kerem"},
@@ -36,9 +45,9 @@ describe("vue-tribute", () => {
] ]
vm.$set("items", newItems) vm.$set("items", newItems)
setTimeout(() => { Vue.nextTick(() => {
expect(vm.$options.directives["tribute"].paramWatchers.values).toHaveBeenCalled() expect(directive.tribute.collection[0].values).toEqual(newItems)
done() done()
}, 0) })
}) })
}) })