v-iterator
Composition of repeatedly used vue UI framework's components. It's declare and controlled by data, you don't have to declear each component at 'template'.
version 1.0.1
- support vuetify.
version 1.0.6
- support AG Grid vue.
version 1.0.8
- suppert AG Chart vue.
version 1.1.0
- support element-ui.
version 1.1.1
- bug fix at statement 'if': boolean value does not work that is included in array.
version 1.1.2
- bug fix : rendering with v-card-subtitle
version 1.1.3
- minior update: add currency at element-ui
installation
install the npm package:
npm i v-iterator --save
Dependency
Required: Lodash
Optional: Vuetify 2.X . AG-Grid . AG-Chart . Element-Ui
Get started
NPM (ES moduels) / installing the package and Vuetify 2.x from scratch:
vuetify.js:
// src/plugins/vuetify.js
import Vue from 'vue'
import Vuetify from 'vuetify/lib'
Vue.use(Vuetify)
const opts = {}
export default new Vuetify(opts)
element.js
// src/plugins/element.js
import Vue from 'vue'
import ElementUI from 'element-ui'
import lang from 'element-ui/lib/locale/lang/en'
import locale from 'element-ui/lib/locale'
import 'element-ui/lib/theme-chalk/index.css'
locale.use(lang)
Vue.use(ElementUI)
Registry <v-iterator> globally in your main.js:
import Vue from 'vue'
import App from './App.vue'
// only when using vuetify
import vuetify from '@/plugins/vuetify'
// only when using element-ui
import 'element-ui'
// import and set v-iterator
import {VIterator} from 'v-iterator'
Vue.component(VIterator.name, VIterator)
// only when using ag-grid
import { AgGridVue } from 'ag-grid-vue'
Vue.component('ag-grid-vue', AgGridVue)
import 'ag-grid-community/dist/styles/ag-grid.css'
import 'ag-grid-community/dist/styles/ag-theme-balham.css'
// only when using ag-chart
import { AgChartsVue } from 'ag-charts-vue'
Vue.component('ag-charts-vue', AgChartsVue)
new Vue({
vuetify,
render: h => h(App)
}).$mount('#app')
Add runtime compiler option at 'vue.config.js'
module.exports = {
runtimeCompiler: true
}
Add externals at vue.config.js:
module.exports = {
configureWebpack: {
externals: {
'element-ui': 'element-ui', // if you don't use element-ui, add this line
'vuetify/lib': 'vuetify/lib' // if you don't use vuetify, add this line
}
}
}
How to use
Api is basically same with original component
<template>
<v-iterator :dynamicArg="screen" :data="$data" @btnClick="btnClick">
</template>
<script>
export default {
data: () => ({
screen: {
items: [
{ component: 'container', framework: 'vuetify', fluid: true, items: [
{ component: 'btn', framework: 'vuetify', color: 'grey lighten-3', itemtext: 'Block Button', style: 'width: 100%;',
evnts: [{ event: 'click', method: 'btnClick'}]
},
{ component: 'card', framework: 'vuetify', flat: true, items: [
{ component: 'card-text', framework: 'vuetify', itemtext: 'textData' }
]}
]}
]
},
textData: 'Button clicked!',
clickedCount: 0
}),
methods: {
btnClick () {
this.clickedCount++
this.textData = String(this.textData).concat(': ', this.clickedCount)
}
}
}
</script>
custom attribute 'framework'
- From version 1.1.0, element-ui framework is supported. So that define framework, this attribute is added.
- value: vuetify (short key: v), element (short key: el)
- default: vuetify
- to change default value: set 'VUE_APP_FRAMEWORK' at your .env file
VUE_APP_FRAMEWORK=element
included vuetify component
Almost vuetify components are supported.
component name
agGrid: 'AG Grid', agd: 'AG Grid', agChart: 'AG Chart', alert: 'Alert', alt: 'Alert', appBar: 'AppBar', appbar: 'AppBar', apb: 'AppBar', autocomplete: 'Autocomplete', aut: 'Autocomplete', avatar: 'Avatar', ava: 'Avatar', badge: 'Badge', bge: 'Badge', banner: 'Banner', bnr: 'Banner', bottomNavigation: 'BottomNavigation', bnavi: 'BottomNavigation', btmnav: 'BottomNavigation', bottomSheet: 'BottomSheet', bsheet: 'BottomSheet', btmsht: 'BottomSheet', breadcrumbs: 'Breadcrumbs', bread: 'Breadcrumbs', brd: 'Breadcrumbs', breadcrumbsItem: 'BreadcrumbsItem', breadItem: 'BreadcrumbsItem', breaditm: 'BreadcrumbsItem', brditm: 'BreadcrumbsItem', button: 'Button', btn: 'Button', buttonToggle: 'ButtonToggle', btnToggle: 'ButtonToggle', btntog: 'ButtonToggle', card: 'Card', crd: 'Card', cardTitle: 'CardTitle', crdtle: 'CardTitle', cardSubtitle: 'CardSubtitle', crdsut: 'CardSubitle', cardText: 'CardText', crdtxt: 'CardText', cardActions: 'CardActions', crdact: 'CardActions', calendar: 'Calendar', caledr: 'Calendar', cal: 'Calendar', carousel: 'Carousel', car: 'Carousel', carouselItem: 'CarouselItem', caritm: 'CarouselItem', carouselTranstion: 'CarouselTranstion', cartrn: 'CarouselTranstion', carouselReverseTranstion: 'CarouselReverseTranstion', carrevtrn: 'CarouselReverseTranstion', chip: 'Chip', chp: 'Chip', chipGroup: 'ChipGroup', chpgrp: 'ChipGroup', checkbox: 'Checkbox', chk: 'Checkbox', col: 'Col', combobox: 'Combobox', com: 'Combobox', container: 'Container', contai: 'Container', currency: 'Currency', cur: 'Currency', dataIterator: 'DataIterator', dtaIte: 'DataIterator', dataFooter: 'DataFooter', dtafoo: 'DataFooter', datePicker: 'DatePicker', date: 'DatePicker', dte: 'DatePicker', dtepik: 'DatePicker', dialog: 'Dialog', dia: 'Dialog', dialogTranstion: 'DialogTranstion', diatrn: 'DialogTranstion', dialogTopTranstion: 'DialogTopTranstion', diatoptrn: 'DialogTopTranstion', dialogBottomTranstion: 'DialogBottomTranstion', diabottrn: 'DialogBottomTranstion', divider: 'Divider', dvd: 'Divider', div: 'Div', expansionPanels: 'ExpansionPanels', expanels: 'ExpansionPanels', exppans: 'ExpansionPanels', expansionPanel: 'ExpansionPanel', expanel: 'ExpansionPanel', exppan: 'ExpansionPanel', expansionPanelHeader: 'ExpansionPanelHeader', expanelh: 'ExpansionPanelHeader', exppanhdr: 'ExpansionPanelHeader', expansionPanelContent: 'ExpansionPanelContent', expanelc: 'ExpansionPanelContent', exppancon: 'ExpansionPanelContent', expandTransition: 'ExpandTransition', exptrn: 'ExpandTransition', fadeTransition: 'FadeTransition', fadtrn: 'FadeTransition', fileInput: 'FileInput', file: 'FileInput', fle: 'FileInput', form: 'Form', frm: 'Form', footer: 'Footer', fter: 'Footer', ftr: 'Footer', hover: 'Hover', hovr: 'Hover', hvr: 'Hover', icon: 'Icon', icn: 'Icon', image: 'Image', img: 'Image', input: 'Input', in: 'Input', inp: 'Input', item: 'Item', itm: 'Item', itemGroup: 'ItemGroup', itmgrp: 'ItemGroup', lazy: 'Lazy', laz: 'Lazy', list: 'List', lst: 'List', listGroup: 'ListGroup', lstgrp: 'ListGroup', listItem: 'ListItem', lstitm: 'ListItem', listItemTitle: 'ListItemTitle', lstitmtle: 'ListItemTitle', listItemSubtitle: 'ListItemSubtitle', lstitmsut: 'ListItemSubtitle', listItemAction: 'ListItemAction', lstitmact: 'ListItemAction', listItemActionText: 'ListItemActionText', lstitmacttxt: 'ListItemActionText', listItemAvatar: 'ListItemAvatar', lstitmava: 'ListItemAvatar', listItemContent: 'ListItemContent', lstitmcon: 'ListItemContent', listItemIcon: 'ListItemIcon', lstitmicn: 'ListItemIcon', listItemGroup: 'ListItemGroup', lstitmgrp: 'ListItemGroup', menu: 'Menu', meu: 'Menu', navigationDrawer: 'NavigationDrawer', navdrw: 'NavigationDrawer', navidrw: 'NavigationDrawer', overflow: 'OverflowButton', overbtn: 'OverflowButton', overlay: 'Overlay', ovl: 'Overlay', pagination: 'Pagination', page: 'Pagination', pag: 'Pagination', parallax: 'Parallax', par: 'Parallax', pax: 'Parallax', progressLinear: 'ProgressLinear', progressL: 'ProgressLinear', prglin: 'ProgressLinear', progressCircular: 'ProgressCircular', progressC: 'ProgressCircular', prgcir: 'ProgressCircular', radio: 'Radio', rdo: 'Radio', radioGroup: 'RadioGroup', radiogrp: 'RadioGroup', rdogrp: 'RadioGroup', rating: 'Rating', rate: 'Rating', rat: 'Rating', range: 'RangeSlider', rangeSlider: 'RangeSlider', rng: 'RangeSlider', rngsld: 'RangeSlider', responsive: 'Responsive', res: 'Responsive', row: 'Row', scrollXTransition: 'ScrollXTransition', scrxtrn: 'ScrollXTransition', scrollYTransition: 'ScrollYTransition', scrytrn: 'ScrollYTransition', select: 'Select', slt: 'Select', sheet: 'Sheet', sht: 'Sheet', simpleTable: 'SimpleTable', simtbl: 'SimpleTable', skeletonLoader: 'SkeletonLoader', skeleton: 'SkeletonLoader', skelod: 'SkeletonLoader', slideItem: 'SlideItem', sliitm: 'SlideItem', slideGroup: 'SlideGroup', sligrp: 'SlideGroup', slider: 'Slider', sld: 'Slider', snackbar: 'Snackbar', sba: 'Snackbar', spacer: 'Spacer', spc: 'Spacer', speedDial: 'SpeedDial', spddil: 'SpeedDial', stepper: 'Stepper', stp: 'Stepper', stepperContent: 'StepperContent', stpcon: 'StepperContent', stepperHeader: 'StepperHeader', stphdr: 'StepperHeader', stepperItems: 'StepperItems', stpitm: 'StepperItems', stepperStep: 'StepperStep', stpstp: 'StepperStep', subheader: 'Subheader', subhdr: 'Subheader', switch: 'Switch', swc: 'Switch', tabItem: 'TabItem', tabitm: 'TabItem', tabReverseTransition: 'TabReverseTransition', tabrevtrn: 'TabReverseTransition', tabTransition: 'TabTransition', tabtrn: 'TabTransition', tabs: 'Tabs', tab: 'Tab', tabsItems: 'TabsItems', tabsitms: 'TabsItems', text: 'Text', txt: 'Text', textarea: 'Textarea', texta: 'Textarea', txta: 'Textarea', textField: 'Textfield', textfield: 'Textfield', txtfld: 'Textfield', toolbar: 'Toolbar', tlb: 'Toolbar', toolbarItems: 'ToolbarItems', tlbitms: 'ToolbarItems', timePicker: 'TimePicker', time: 'TimePicker', tim: 'TimePicker', treeview: 'Treeview', tre: 'Treeview', tree: 'Treeview', window: 'Window', win: 'Window', windowItem: 'WindowItem', winitm: 'WindowItem'
Event
Please set method name that related with event at v-on of v-iterator.
<template> <v-iterator :dynamicArg="screen" :data="$data" @btnClick="btnClick"> </tempalte> <script> export default { data: () => ({ screen: { items: [ { component: 'container', fluid: true, items: [ { component: 'btn', color: 'grey lighten-3', itemtext: 'Block Button', style: 'width: 100%;', evnts: [{ event: 'click', method: 'btnClick'}] }, { component: 'card', flat: true, items: [ { component: 'card-text', itemtext: 'textData' } ]} ]} ] }, textData: 'Button clicked!', clickedCount: 0 }), methods: { btnClick () { this.addCount() }, addCount () { this.clickedCount++ this.textData = String(this.textData).concat(': ', this.clickedCount) } } } </script>
Slot
If you want to use slot of vuetify component, set like below
use slot without return value of slot
{ component: 'btn', loading: true, itemtext: 'custom loader', slots: [ { name: 'loader', items: [{ component: 'text', class: 'ma-0 pa-0', itemtext: 'Loading...' }] } ] }
use slot with return value of slot
{ component: 'carousel', showArrowsOnHover: true slots: [ { name: 'prev', type: 'data', slotDataName: 'slot', items: [ { component: 'btn', attrs: 'slot.attrs', on: 'slot.on', color: 'success', itemtext: 'previous' } ]} ] }
Etc
i18n
If you want to use i18n code at lable or text, just use code name like this.
{ component: 'btn', label: 'common.confirm' }
or
{ component: 'btn', label: this.$t('common.confirm') }
reference
When you call child component's function at vuetify, need reference like this.
original vuetify
<template>
<v-form ref="form" v-model="valid" lazy-validation>
<v-text-field v-model="text" label="text"/>
<v-btn @click="save">Validate</v-btn>
</v-form>
</template>
<script>
export default {
data () {
return {
text: '',
valid: true
}
},
methods: {
save () {
this.$refs.form.validate()
}
}
}
</script>
v-iterator
<template>
<v-iterator ref="iterator", :dynamicArg="screen" :data="data" @save="save"/>
</template>
<script>
export default {
data () {
return {
screen: {
items: [
{ component: 'form', ref: 'form', model: 'valid', 'lazy-validation': true,
items: [
{ component: 'text-field', model: 'text', label: 'text' },
{ component: 'btn', itemtext: 'Validate', evnts: [{event: 'click', method: 'save'}]}
]
}
]
},
data: {
text: '',
valid: true
}
}
},
methods: {
save () {
this.$refs.iterator.getRef('form').validate()
}
}
}
</script>
v-for
v-iterator use prop name 'itemsfor' instead of 'v-for'.
original vuetify
<template>
<v-sheet>
<v-tabs dark show-arrows>
<v-tab v-for="i in 30" :key="i">
Item {{ i }}
</v-tab>
</v-tabs>
</v-sheet>
</template>
v-iterator
<template>
<v-iterator :dynamicArg="screen">
</template>
<script>
export default {
data () {
return {
screen: {
items: [
{ component: 'sheet', items: [
{ component: 'tabs', dark: true, 'show-arrows': true,
itemsfor: 30, subItemName: 'i', items: [
{ component: 'tab', itemtext: {value: i, func: e => `Item ${e}`}}
]
}
]}
]
}
}
}
}
</script>
v-if
v-if is replaced by 'if' array. All object in 'if' array is connected by 'and' condition.
vuetify
<template>
<v-text-field v-model="name" label="Name"/>
<v-text-field v-model="email" label="e-mail"/>
<v-checkbox v-model="agree" label="Agree">
<v-btn v-if="name && email && agree === true">Submit</b-btn>
<v-btn v-else>Clear</v-btn>
</template>
<script>
export default {
....
}
</script>
v-iterator
<template>
<v-iterator :dynamicArg="screen" :data="data">
</template>
<script>
export default {
data () {
return {
screen: {
items: [
{ component: 'text-field', model: 'name', label: 'Name' },
{ component: 'text-field', model: 'email', label: 'E-mail' },
{ component: 'checkbox', model: 'agree', label: 'Agree' },
{ component: 'btn', if: [{target: 'name'}, {target: 'email'}, {target: 'agree', value: true}], itemtext: 'Submit' },
{ component: 'btn', if: [{target: '_self', value: ({name, email, agree}) => name && email && agree === true, ne: true}], itemtext: 'Clear' }
]
},
data: {
name: null,
email: null,
agree: false
}
}
}
}
</script>
or
data () {
return {
screen: {
items: [
{ component: 'text-field', model: 'name', label: 'Name' },
{ component: 'text-field', model: 'email', label: 'E-mail' },
{ component: 'checkbox', model: 'agree', label: 'Agree' },
{ component: 'btn', itemtext: this.btnText}
]
},
data: {
name: null,
email: null,
agree: false
}
}
},
computed: {
btnText () {
return this.data.name && this.data.email && this.data.agree === true ? 'Submit' : 'Clear'
}
}
or
data () {
return {
screen: {
items: [
{ component: 'text-field', model: 'name', label: 'Name' },
{ component: 'text-field', model: 'email', label: 'E-mail' },
{ component: 'checkbox', model: 'agree', label: 'Agree' },
{ component: 'btn', itemtext: 'btnText' }
]
},
data: {
name: null,
email: null,
agree: false,
btnText: 'Clear'
}
}
},
watch: {
'data.name' () {
this.getBtnText()
},
'data.email' () {
this.getBtnText()
},
'data.agree' () {
this.getBtnText()
}
},
methods: {
getBtnText () {
this.data.btnText = this.data.name && this.data.email && this.data.agree === true ? 'Submit' : 'Clear'
}
}