What is the best way to set up v-models for complex arrays or nested objects?

I'm looking to efficiently create multiple v-models for random properties within a deep array, where the position of attributes in arrays/objects can change dynamically. While I've managed to achieve my goal with the current setup, I'll need to render several fields in different locations on the page, making the use of v-for impractical. Is there a way to simplify this code?

<template>
  <div class="builder">
    <div class="sidebar">
      <div class="block">
        <input v-model="template[headTagIndex].children[headTagAttributesIndex].children[headTagAttributesAllIndex].attributes['font-family']" placeholder="General Font" type="text">
      </div>
    </div>
    <div class="editor">
      <div v-if="compiledTemplate" v-html="compiledTemplate.html"/>
      <div v-else>Loading</div>
    </div>
    <div class="ads"/>
  </div>
</template>

<script setup>
const {$mjml} = useNuxtApp()

const template = ref([
  {
    "tagName": "mj-head",
    "children": [
      {
        "tagName": "mj-attributes",
        "children": [
          {
            "tagName": "mj-all",
            "attributes": {
              "font-family": "Comic sans-serif"
            }
          }
        ]
      }
    ]
  },
  {
    "tagName": "mj-body",
    "children": [
      {
        "tagName": "mj-section",
        "attributes": {
          "background-color": "red"
        },
        "children": [
          {
            "tagName": "mj-column",
            "attributes": {
              "padding-top": "100px",
              "padding-bottom": "100px"
            },
            "children": [
              {
                "tagName": "mj-text",
                "attributes": {
                  "align": "center",
                  "color": "#F45E43"
                },
                "content": "Testing component"
              }
            ]
          }
        ]
      },
      {
        "tagName": "mj-section",
        "attributes": {
          "full-width": "full-width",
          "background-color": "blue"
        },
        "children": [
          {
            "tagName": "mj-column",
            "attributes": {
              "padding-top": "100px",
              "padding-bottom": "100px"
            },
            "children": [
              {
                "tagName": "mj-text",
                "attributes": {
                  "align": "center",
                  "color": "#F45E43"
                },
                "content": "Testing component"
              }
            ]
          }
        ]
      },
      {
        "tagName": "mj-section",
        "attributes": {
          "background-color": "pink"
        },
        "children": [
          {
            "tagName": "mj-column",
            "attributes": {
              "padding-top": "100px",
              "padding-bottom": "100px"
            },
            "children": [
              {
                "tagName": "mj-text",
                "attributes": {
                  "align": "center",
                  "color": "#F45E43"
                },
                "content": "Testing component"
              }
            ]
          }
        ]
      },
      {
        "tagName": "mj-section",
        "attributes": {
          "full-width": "full-width",
          "background-color": "teal"
        },
        "children": [
          {
            "tagName": "mj-column",
            "attributes": {
              "padding-top": "100px",
              "padding-bottom": "100px"
            },
            "children": [
              {
                "tagName": "mj-text",
                "attributes": {
                  "align": "center",
                  "color": "#F45E43"
                },
                "content": "Testing component"
              }
            ]
          }
        ]
      }
    ]
  }
])

const headTagIndex = indexOfHeadTag(template.value)
console.log(headTagIndex)
const headTagAttributesIndex = indexOfHeadTagAttributes(template.value, headTagIndex)
console.log(headTagAttributesIndex)
const headTagAttributesAllIndex = indexOfHeadTagAttributesAll(template.value, headTagIndex, headTagAttributesIndex)
console.log(headTagAttributesAllIndex)

const compiledTemplate = generateCompiledTemplate($mjml, template.value)
</script>

The areas that require optimization are:

v-model="template[headTagIndex].children[headTagAttributesIndex].children[headTagAttributesAllIndex].attributes['font-family']"

And:

const headTagIndex = indexOfHeadTag(template.value)
console.log(headTagIndex)
const headTagAttributesIndex = indexOfHeadTagAttributes(template.value, headTagIndex)
console.log(headTagAttributesIndex)
const headTagAttributesAllIndex = indexOfHeadTagAttributesAll(template.value, headTagIndex, headTagAttributesIndex)
console.log(headTagAttributesAllIndex)

Answer №1

Discovering attributes can be done in a single line using the .find() method:

const attributes = template.value.find(tag => tag.tagName === 'mj-head')
   ?.children?.find(tag => tag.tagName === 'mj-attributes')
   ?.children?.find(tag => tag.tagName === 'mj-all')
   ?.attributes;

The v-model implementation will then appear as follows:

<input v-model="attributes['font-family']" placeholder="General Font" type="text"/>

Try out the Vue SFC Playground

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Struggling to implement server side processing with Datatables in MVC4?

Greetings, our current setup involves an MVC4 application that is handling a large number of records with thumbnail images in a jQuery Datatables driven view. Unfortunately, the loading time is slow due to all thumbnails being fetched at once during a GET ...

Displaying hidden Divs in React Typescript that are currently not visible

I have an array with various titles ranging from Title1 to Title8. When these titles are not empty, I am able to display their corresponding information successfully. Now, my goal is to include a button that will allow me to show all fields. For example, ...

Execute the function upon clicking

When I click on an icon, I want it to blink. This is the code in my typescript file: onBlink() { this.action = true; setTimeout(() => { this.action = false; }, 1000) return this.action }; Here is how the action is declared in my ...

Please disable zoom functionality on the website specifically for Android devices

Is there a way to disable the zoom feature on our website specifically for Android phones/devices without affecting iPhones? Perhaps targeting the Chrome browser on Android would be sufficient, but we should also verify the mobile screen size. ...

Mapping Vue routes to perform redirects

Looking for a quick solution here. Here is the mapping I am working with: const routes = routeOptions.map((route) => { return { children: route?.children?.map((child) => { return { ...{ path: child.path, name: ...

Basic math tool using JSP/Servlet combination and Ajax

I have a follow-up question to my previous inquiry on Stack Overflow. I believe this topic deserves its own discussion due to the thorough response I received. My goal is to develop a straightforward calculator using JSP. The calculator will include two t ...

Tips for updating server-side variables from the client-side in Next.js

There is a code snippet in api/scraper.js file that I need help with. const request = require("request-promise"); const cheerio = require("cheerio"); let url = "https://crese.org/distintivo-azul/"; let result; request(url, ...

What is the reason behind JavaScript events causing a page refresh?

My code uses RegExp to search through an array of strings based on user input: Clinica.prototype.pesquisarDoente = function () { var exp = document.getElementById("pesquisaInput").value; var lista = document.getElementById("listaDoentes"); if ...

What is the method for retrieving a value from my Node.js module once it has been modified by an asynchronous function?

Apologies, but as a beginner developer, I'm struggling to see how this relates directly to the questions already mentioned. I have no understanding of ajax and I'm unsure how to adapt the solutions provided to my own situation. Currently, I&apos ...

No instances are returned by Processing.instances

I am experiencing an issue with a webpage that is running 2 processing sketches. I came across a suggestion to call Processing.instances[0].exit() in response to a question on dynamically unloading a Processing JS sketch from canvas. However, when I attem ...

Understanding how to break down intricate JSON strings into classes using either VB or C# programming languages

I have a JSON string that needs to be parsed and eventually stored in database tables. My plan is to parse it into VB .NET classes (objects) and then store the data in the tables. I have Newtown imported into my .NET environment, but I'm not very fami ...

Is it possible to incorporate vector graphics/icons by simply adding a class to a span element in HTML5?

In order to add a glyphicon icon to our webpage, we simply need to include its class within a span element, as demonstrated here: <span class="glyphicon glyphicon-search"></span> We also have a few files in .ai format that can be converted to ...

Tips on solving the "net::ERR_SSL_SERVER_CERT_BAD_FORMAT" issue while working with Vue.js and Node.js using HTTPS and Express

I encountered an issue while trying to send HTTPS requests in Vue.js using actions methods in Vuex. The console displayed the following error: GET https://localhost/api/getpeople net::ERR_SSL_SERVER_CERT_BAD_FORMAT Here is a snippet of my code: vue ...

Ways to extract the value from a jQuery object

How can I retrieve the selected time value using a jQuery plugin and save it on a specific input element within the page? Refer to the plugin and code provided below: http://jsfiddle.net/weareoutman/YkvK9/ var input = $('#input-a'); input.cloc ...

Tips for dynamically loading JSON data in Pug and JavaScript by implementing scroll functionality

This is my pug file for specificBike in allBikeData .bikeshop-card.border.border-dark.bg-white.m-3.p-4 li img.shop-image.border.border-dark(src=specificBike.image, onerror="this.onerror=null; this.src=&a ...

Tips for sending a JavaScript object from PHP to AJAX

I've been racking my brain for hours, scouring through countless articles, but I'm still unable to crack this puzzle. Here's the situation: I'm currently tinkering with Chrome extensions and I need to make a server call that will fetch ...

Adjust the size of an input field in jquery or javascript based on user input

Ensure that an input text box can only contain a maximum of 13 numbers, but if the user enters a 14th number as a decimal point, then allow up to 16 numbers. HTML: <input type="text" maxlength="15" onkeyup="checkCurrency(this)"/> Script: func ...

Issue occurred while executing the fs.rename() function in a loop in Node.js

I'm currently working on a project that involves organizing uploaded files into folders based on their request ID. I am using express-request-id to retrieve this ID. The issue I am facing is that whenever there are multiple files to be moved, the pro ...

Tips on creating a keypress function for a div element with the contenteditable attribute

Hey there, I have managed to create a textarea within a div by using -webkit-appearance. However, I am currently struggling to add an event to this div on key press. I have been trying my best to figure it out but seem to be missing something. If you coul ...

Utilizing various layouts in ASP.NET MVC with AngularJS

I am setting up two different layouts, one for visitors and one for management. Routes: app.config(['$routeProvider', function ( $routeProvider) { $routeProvider .when('/', { templateUrl: 'Home ...