0

For a document editor tool I need to replace strings with clickable-elements, so the user can input the right values for these variables. For example ("$Year" & "$SomeName"):

Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the $Year an unknown printer took a galley of type and scrambled it to make a type specimen book $SomeName}. It has survived not only five centuries, but also the eap into electronic typesetting, remaining essentially unchanged.

I can use a regex to find and replace the $Variable strings.

However I want to replace the strings with reactive html elements (for example ) so I can bind them to a method in my Vue component, like this:

<span @click="showVariablePopup('SomeName')">$SomeName</span>

Of course this won't work if I just replace these variable-strings with the code above and display the html like this:

<div v-html="stringWithReplacements"></div>

Is there any way i can achieve this?

klaaskox
  • 329
  • 4
  • 15
  • There is! See https://stackoverflow.com/a/44372419/3412322 - basically use Vue.compile() after running your regex to translate the string back into usable components. – Daniel Beck Mar 17 '23 at 15:59

1 Answers1

0

Here is a simple solution, where the text is parsed into text nodes and variable nodes, then you can just print the text nodes and do whatever you want to do with the variable nodes:

const text = `Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the $Year an unknown printer took a galley of type and scrambled it to make a type specimen book $SomeName}. It has survived not only five centuries, but also the eap into electronic typesetting, remaining essentially unchanged.`

const parseText = (text) => {
  const parts = []
  while (text) {
    const nextVarIx = text.search(/\$\w+/)
    if (nextVarIx === -1) {
      parts.push({
        text
      })
      break
    }
    if (nextVarIx > 0) {
      parts.push({
        text: text.substring(0, nextVarIx)
      })
      text = text.substring(nextVarIx)
    }
    const varEnd = 1 + text.search(/\w\b/)
    const variable = text.substring(0, varEnd)
    parts.push({
      variable,
      value: '<Click to change>'
    })
    text = text.substring(varEnd)
  }
  return parts
}

new Vue({
  el: '#app',
  methods: {
    fill(variable) {
      variable.value = (Math.random() + 1).toString(36).substring(7)
    },
  },
  data() {
    return {
      textData: parseText(text),

    };
  },
})
.text-variable {
  font-weight: bold;
}
.text-variable:hover {
  cursor: pointer;
}
<div id="app">
  <div>
    <template v-for="(part, index) in textData" :key="index">
      <span v-if="part.variable" class="text-variable" @click="fill(part)">
        {{ part.value }}
      </span>
      <span v-else>{{ part.text }}</span>
    </template>
  </div>
</div>

<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.7.10/vue.min.js"></script>
<script src="https://unpkg.com/v-calendar"></script>
Moritz Ringler
  • 9,772
  • 9
  • 21
  • 34