Logical component vs presentation component

I tried to create a logical structure for my new Vue project, and I ran into the wall. Really. Let’s check what I mean and how I will resolve it.

Presentation component

I like to split my project into two important parts. First of it is a presentation layer. So here, I have a lot of components like buttons, tables, inputs, etc. In components of this type, I’m focusing on proper work and look for only this component. For example. Here You can see part of my input component (just example code):

<template>
  <label>
    {{ label }}
    <input type="text" v-model="value">
  </label>
</template>

<script lang="ts">
import { defineComponent, ref } from 'vue';

export default defineComponent({
  props: {
    label: {
      type: String,
      default: '',
    },
  },
  setup() {
    const value = ref('');
    return {
      value,
    };
  },
});
</script>

<style lang="sass">
@import '@/styles/components/input'
</style>

As you can see there is nothing hard to explain. Just an example Vue implementation of input. Add the bottom I included scss file with styles for it. I like to split css from the .vue file. For me, it’s easier to maintain a structure like that.

Logical component

Logical component is a place where I can match a few presentation components in one bigger. And it’s easy to do but here I have problem. Naming convention. This is my problem. How to call this type of component? Where to place it? But first maybe some example. I want to create component like that:

<template>
    <form class="app_form" @submit.prevent="">
      <app-input label="Title:" v-model="formData."></app-input>
      <app-input label="Category:" @input="updateCategory"></app-input>
      <app-input label="Date:" @input="updateDate"></app-input>
      <app-input label="Amount:" @input="updateAmount"></app-input>
      <app-input label="Comment:" @input="updateComment"></app-input>
      <app-button @click="addNewExpense">Create</app-button>
    </form>
</template>

<script lang="ts">
import { defineComponent, reactive } from 'vue';
import { AppInput, AppButton } from '@/components';

export default defineComponent({
  setup() {
    const formData = reactive({
      title: '',
      category: '',
      date: '',
      amount: '',
      comment: '',
    });
    
    return {
      formData,
    };
  },
});
</script>

Like you can see, this component is created for grouping inputs in one form. Here I will put more logic in the future, but there will be no css and no other visual changes. So how should I call it? It is a Vue component for sure. But it should not change anything in UI. I created it only for the logical grouping of some components. Maybe you don’t have a problem like this, but it’s really bothering me.

Proper structure of project always makes work easier and faster. And this is the point. I like my project structure but I always have a problem with logical components in Vue. Previous I called it partials. But this name looks a little bit messy now.

How to solve it?

Well, it seems like there is no good solution. Unfortunately. For this project, I will create a new folder and there I will put all of these logical components. I will call it blocks. It’s not the best solution for sure but for now, it’s the best what I can invent. Why blocks? Because it’s something more than a component but it’s not a view. It’s something between these two parts of the code.

Your solution?

Maybe you have another solution for this problem? If, then share it in comments below. It will help all of us! Thanks a lot and see you soon.