This document provides an overview and introduction to creating data-driven user interfaces with Vue components. It discusses what a data-driven dynamic UI is and when it would be needed. It then covers the basics of using the <component> tag to dynamically load components based on a prop, data property, or computed property. It discusses how props and events can be used with dynamic components, including how unknown props are handled. Finally, it demonstrates how to build dynamic forms using a JSON schema and dynamically loading form components based on field types, including handling data binding and updating form data.
5. DATA DRIVEN INTERFACES
WHATS COMING UP?
▸ What is a Data Driven Dynamic UI?
▸ Understanding `<component>`
▸ Basic use
6. DATA DRIVEN INTERFACES
WHATS COMING UP?
▸ What is a Data Driven Dynamic UI?
▸ Understanding `<component>`
▸ Basic use
▸ Props and Events
7. DATA DRIVEN INTERFACES
WHATS COMING UP?
▸ What is a Data Driven Dynamic UI?
▸ Understanding `<component>`
▸ Basic use
▸ Props and Events
▸ Dynamic Forms
14. “
“DYNAMIC COMPONENTS ARE NOT A COMMON REQUIREMENT”
BLOG POST I (SORTA) DISAGREE WITHBLOG POST I (SORTA) DISAGREE WITH
15. CAN BE AN ELEGANT SOLUTION FOR
▸ Workflow Builders
WHAT DO WE MEAN?
16. CAN BE AN ELEGANT SOLUTION FOR
▸ Workflow Builders
▸ Personalization
WHAT DO WE MEAN?
17. CAN BE AN ELEGANT SOLUTION FOR
▸ Workflow Builders
▸ Personalization
▸ A/B Testing
WHAT DO WE MEAN?
18. CAN BE AN ELEGANT SOLUTION FOR
▸ Workflow Builders
▸ Personalization
▸ A/B Testing
‣ Data Driven Customization
WHAT DO WE MEAN?
19. CAN BE AN ELEGANT SOLUTION FOR
▸ Workflow Builders
▸ Personalization
▸ A/B Testing
‣ Data Driven Customization
▸ Form Generators
WHAT DO WE MEAN?
20. CAN BE AN ELEGANT SOLUTION FOR
▸ Workflow Builders
▸ Personalization
▸ A/B Testing
‣ Data Driven Customization
▸ Form Generators
▸ … and lots more
WHAT DO WE MEAN?
32. “
SPEND TIME BUILDING SOLUTIONS WITH THEM.
NOT TRYING TO FIGURE OUT HOW TO LOAD COMPONENTS DYNAMICALLY.
33. THE BASICS - COMPONENT
▸ Component is a place holder
<component :is=“componentType”/>
<section class="markup-demo-wrap">
<component :is="activeView" v-model="contact">
</component>
</section>
<component :is=“componentType"/>
34. THE BASICS - COMPONENT
▸ Component is a place holder
<component :is=“componentType”/>
<section class="markup-demo-wrap">
<component :is="activeView" v-model="contact">
</component>
</section>
<component :is=“componentType"/>
35. THE BASICS - COMPONENT
▸ Component is a place holder
<component :is=“componentType”/>
<section class="markup-demo-wrap">
<component :is="activeView" v-model="contact">
</component>
</section>
<component :is=“componentType"/>
36. THE BASICS - COMPONENT
▸ Component is a place holder
▸ Does not introduce any host elements
<component :is=“componentType”/><component :is=“componentType"/>
37. THE BASICS - COMPONENT
<component :is=“componentType"/>
38. THE BASICS - COMPONENT
<component :is="componentType"/>
39. THE BASICS - COMPONENT
▸ :is can bound to
<component :is="componentType"/>
40. THE BASICS - COMPONENT
▸ :is can bound to
▸ Prop
<component :is="componentType"/>
41. THE BASICS - COMPONENT
▸ :is can bound to
▸ Prop
▸ Data Property
<component :is="componentType"/>
42. THE BASICS - COMPONENT
▸ :is can bound to
▸ Prop
▸ Data Property
▸ Computed Property
<component :is="componentType"/>
43. THE BASICS - COMPONENT
▸ :is can bound to
▸ Prop
▸ Data Property
▸ Computed Property
▸ Can be derived from Vuex store
<component :is="componentType"/>
53. PROPS AND EVENTS
DO WE NEED TO KNOW ALL PROPS UP FRONT?
▸ No, “v-bind” to the rescue
54. PROPS AND EVENTS
DO WE NEED TO KNOW ALL PROPS UP FRONT?
▸ No, “v-bind” to the rescue
▸ Object Properties that match Props get bound as Props
55. PROPS AND EVENTS
DO WE NEED TO KNOW ALL PROPS UP FRONT?
▸ No, “v-bind” to the rescue
▸ Object Properties that match Props get bound as Props
<component :is="activeView"
:firstName="contact.firstName"
:lastName="contact.lastName"
:password="contact.password"
:email="contact.email"
:userName="contact.userName"
:street1="contact.street1"
:street2="contact.street2"
:country="contact.country"
:postalCode="contact.postalCode"
:province="contact.province">
</component>
V-BIND BEFORE
56. PROPS AND EVENTS
DO WE NEED TO KNOW ALL PROPS UP FRONT?
▸ No, “v-bind” to the rescue
▸ Object Properties that match Props get bound as Props
<component :is="activeView"
:firstName="contact.firstName"
:lastName="contact.lastName"
:password="contact.password"
:email="contact.email"
:userName="contact.userName"
:street1="contact.street1"
:street2="contact.street2"
:country="contact.country"
:postalCode="contact.postalCode"
:province="contact.province">
</component>
V-BIND BEFORE
<component :is="activeView"
v-bind="contact">
</component>
V-BIND AFTER
59. PROPS AND EVENTS
WHAT HAPPENS TO THE OTHER PROPS?
▸ Available in $attrs
▸ inheritAttrs: true (default)
60. PROPS AND EVENTS
WHAT HAPPENS TO THE OTHER PROPS?
▸ Available in $attrs
▸ inheritAttrs: true (default)
▸ Become attributes on the root of the component
61. PROPS AND EVENTS
WHAT HAPPENS TO THE OTHER PROPS?
▸ Available in $attrs
▸ inheritAttrs: true (default)
▸ Become attributes on the root of the component
▸ inheritAttrs: false
62. PROPS AND EVENTS
WHAT HAPPENS TO THE OTHER PROPS?
▸ Available in $attrs
▸ inheritAttrs: true (default)
▸ Become attributes on the root of the component
▸ inheritAttrs: false
▸ Can control how they are bound
63. PROPS AND EVENTS
INHERITATTRS: TRUE (DEFAULT)
▸ Become attributes on the root element of the component
contact: {
street1: "19 York Street",
street2: "6th Floor",
country: "Canada",
postalCode: "N1N 2N2",
province: "Ontario",
firstName: "Evan",
lastName: "Schultz",
password: "iwantmymoney",
email: "evan@",
userName: "e-schultz",
}
CONTACT UNKNOWN PROPS
65. PROPS AND EVENTS
INHERITATTRS: FALSE
▸ Can control where they are bound
<label>{{label}}</label>
<input type="text"
:name="name"
:placeholder="placeholder"
v-bind="$attrs">
66. PROPS AND EVENTS
INHERITATTRS: FALSE
▸ Can control where they are bound
▸ Can pass down to other components
<label>{{label}}</label>
<input type="text"
:name="name"
:placeholder="placeholder"
v-bind="$attrs">
67. PROPS AND EVENTS
INHERITATTRS: FALSE
▸ Can control where they are bound
▸ Can pass down to other components
▸ Useful for working with other libraries
<b-dropdown :value="value"
@input="$emit('input',$event)"
v-bind="$attrs">
<!-- ... -->
<b-dropdown-item v-for="(option) in options" :key="option"
:value="option">
{{option}}
</b-dropdown-item>
</b-dropdown>
86. FORMS
WHAT ABOUT V-IF
▸ Still useful for simple cases
▸ Can quickly bloat templates
▸ Repetitive code can become error prone
87. FORMS
WHAT ABOUT V-IF
<div v-for="(field, index) in schema" :key="index">
<text-input v-if="field.fieldType === 'TextInput'"
:value="formData[field.name]"
@input="updateForm(field.name, $event)"
v-bind="field.props"></text-input>
<password-input v-else-if="field.fieldType === 'PasswordInput'"
:value="formData[field.name]"
@input="updateForm(field.name, $event)"
v-bind="field.props"></password-input>
<select-list v-else-if="field.fieldType === 'SelectList'"
:value="formData[field.name]"
@input="updateForm(field.name, $event)"
v-bind="field.props"></select-list>
<!--- and repeat for each dynamically loadable component -->
</div>
88. FORMS
WHAT ABOUT V-IF
<component v-for="(field, index) in schema"
:key="index"
:is="field.fieldType"
:value="formData[field.name]"
@input="updateForm(field.name, $event)"
v-bind="field.props">
</component>
90. FORMS
DATA BINDING - EXPLORING V-MODEL
<input v-model="value">
<input :value="value" @input=“value = $event.target.value">
IS SUGAR ON TOP OF
91. FORMS
DATA BINDING - GOALS FOR THE COMPONENT
▸ Let the parent provide a value to the child component
▸ Let the parent know that the value has changed
92. FORMS
DATA BINDING - GOALS FOR THE COMPONENT
<label>{{label}}</label>
<input type="text"
:name="name"
:value="value"
@input="$emit('input',$event.target.value)"
:placeholder="placeholder">
93. ▸ Bind to “:value”
FORMS
DATA BINDING - GOALS FOR THE COMPONENT
<label>{{label}}</label>
<input type="text"
:name="name"
:value="value"
@input="$emit('input',$event.target.value)"
:placeholder="placeholder">
94. ▸ Bind to “:value”
▸ Emit an “@input” event to notify the parent
FORMS
DATA BINDING - GOALS FOR THE COMPONENT
<label>{{label}}</label>
<input type="text"
:name="name"
:value="value"
@input="$emit('input',$event.target.value)"
:placeholder="placeholder">
95. FORMS
DATA BINDING - COMPONENT WITH V-MODEL
<component v-for="(field, index) in schema"
:key="index"
:is="field.fieldType"
v-model="formData[field.name]"
v-bind="field">
</component>
export default {
data() {
return {
formData: {
firstName: 'Evan'
},
schema: [ { /* .... */ }]
}