Loading the schema and creating a Renderer component

Now that we have a basic schema set up to work with, let's go ahead and load into the application so that we can use it. Later on in this chapter, we are going to create a dummy API that will feed us the data in a slightly different way, and we will transform it on our end to fit our app's requirements.

For now, let's go to App.vue and import the JSON. We will start by adding the following import statement to the top near the other import statements:

import schema from '@/data/schema.json';

Now that we have our data available to our application, we need some components to be able to parse this information into the BaseInput and BaseSelect components. Let's go ahead and create a new file inside the components folder, and name it Renderer.vue. This component will have a single purpose: to understand our schema and render the correct component to the screen. It will currently have a single property, element, which represents each of the elements in our schema. To do so, add the following code to Renderer.vue:

      <template>
<component
:is="component"
v-bind="props"
/>
</template>
<script>
export default {
props: {
element: {
type: Object,
required: true
}
},
computed: {
component() {
const componentName = this.element.component;
return () => import(`./${componentName}`);
},
props() {
return this.element;
}
}
}
</script>

There's a couple of important things to note in this component. They are as follows:

  • The element prop is an object and will be required. This component will not work at all without it. We have two computed properties. The first component takes care of dynamically loading whichever element we need. First, we create a componentName constant and assign it to the value of element.component, which is where the string name of our component is stored in the schema.
  • It's important to mention that we are not just adding this const for clarity purposes. The way that computed properties work regarding caching requires that this const exists here since we are returning a function, which will not be inspected for dependencies.
  • When this computed property is called by the <component> tag for the : is an attribute—it will load the component and pass it over. Note that this will only work if the component is globally registered; in any other case, a computed property that requires the correct component would be needed. For further information on dynamic components, check out the official documentation: https://vuejs.org/v2/guide/components-dynamic-async.html.

The second computed property, props, will simply pass down the whole element with its properties as props to whatever component we are loading using the v-on binding. For example, on the BaseSelect component, it will pass down the options property in our schema to the component so that it can render the correct options. If you are wondering why we are using a computed property instead of just passing the element directly to the v-on directive, you are on the right track. Right now, it is definitely not needed, but having it set up in this way to begin with allows us to, later on, add another level of logic or parsing that could be needed for a particular component.

Let's head back to App.vue.

We need to import our Renderer component and add it to the template. We also need to clean up a bit; we no longer need to manually import BaseInput or BaseSelect, and our form local state will be soon dynamic—so, there's no need to declare it statically, as shown in the following code snippet:

      <template>
<div id="app" class="container py-4">
<div class="row">
<div class="col-12">
<form>
<Renderer
v-for="(element, name) in schema"
:key="name"
:element="element"
/>
<div class="form-group">
<button
@click.prevent="onSubmit"
type="submit"
class="btn btn-primary"
>Submit</button>
</div>
</form>
</div>
</div>
</div>
</template>

<script>
import schema from '@/data/schema.json';
import Renderer from '@/components/Renderer';
export default {
name: 'app',
components: { Renderer },
data() {
return {
schema: schema,
form: {}
}
},
methods: {
onSubmit() {
console.log('Submit clicked');
}
}
}
</script>

Go ahead and run it in the browser and you should see the three inputs that the schema declared in schema.json, and the <select> should have our three options inside of it. You are going to get a couple of console errors at this point because we haven't worked on our two-way value bindings for our components, and they're set as required. But don't worry, we'll get back to that soon!

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.138.122.4