【发布时间】:2021-09-25 00:05:42
【问题描述】:
我有一个 vuejs 页面,我正在动态创建 DOM 输入,我想将它们与一组 3 个表单变量绑定以捕获数据。 我不知道从一开始他们将创建多少组输入来初始化表单条目。 表单是在 Vue 的 setup() 部分使用 useForm 创建的。 以下是代码片段。
<template>
<app-layout>
<template #header>
<h2 class="font-semibold text-xl text-gray-800 leading-tight">
{{ title }}
</h2>
</template>
<div class="py-12">
<div class="max-w-7xl mx-auto sm:px-6 lg:px-8">
<div class="bg-white overflow-hidden shadow-xl sm:rounded-lg">
<div class="audio_edit">
<form @submit.prevent="form.post('/pppaudio/newProcessedAudio')">
<div class="pp_title">
<label style="font-weight: bold">
Title:
</label>
<label for="title">{{ title }}</label>
</div>
<div class="pp_audio">
<div id="waveform"></div>
<div id="wave-timeline"></div>
<div class="playButton">
<Button data-action="play" type="button">
<span id="play">
<i class="glyphicon glyphicon-play"></i>
Play
</span>
<span id="pause" style="display: none">
<i class="glyphicon glyphicon-pause"></i>
Pause
</span>
</Button>
</div>
</div>
<div class="pp_transcript flex flex-col">
<label style="font-weight: bold">
Transcript:
</label>
{{ transcript }}
</div>
<div id="region_block" ref="reg_block" >
<div class="region">
<div id="copyTextButton" class="copyButton">
<Button v-on:click="getText" type="button">Copy Marked Text</Button>
</div>
<div class="pp_new_transcript flex flex-col">
<label style="font-weight: bold">
New Transcript:
</label>
<textarea id="selectedText" rows="5" class="selectedTextInput h-full" v-model="form.selectedText" />
</div>
<div class="pp_start-stop">
<label for="start" style="font-weight: bold">
Start:
</label>
<input id="start" v-model="form.start" disabled/>
<label for="stop" style="font-weight: bold">
Stop:
</label>
<input id="stop" v-model="form.stop" disabled/>
</div>
<div id="submit_button">
<Button>Submit</Button>
</div>
</div>
</div>
<div id="return_back">
<Button v-on:click="goBack" type="button">Back</Button>
</div>
</form>
</div>
</div>
</div>
</div>
</app-layout>
</template>
<script>
import AppLayout from "../../Layouts/AppLayout";
import Label from "../../Jetstream/Label";
import Button from "../../Jetstream/Button";
import {InputFacade} from 'vue-input-facade';
import WaveSurfer from 'wavesurfer.js';
import RegionPlugin from 'wavesurfer.js/dist/plugin/wavesurfer.regions.js';
import TimeLine from 'wavesurfer.js/dist/plugin/wavesurfer.timeline.js';
import {useForm} from '@inertiajs/inertia-vue3';
import Vue from 'vue'
export default {
setup() {
const form = useForm({
title: null,
selectedText: null,
start: null,
stop: null,
})
return {form}
},
components: {Button, Label, AppLayout, InputFacade},
methods: {
getText() {
this.newTranscript = window.getSelection().toString();
this.form.selectedText = this.newTranscript;
this.form.title = this.title;
},
copyValues(start, stop) {
this.form.start = start;
this.form.stop = stop;
},
goBack() {
let formData = new FormData();
formData.append('id', localStorage.id);
axios.post('/pppaudio/goBack',
formData, {
headers: {
'Content-Type': 'multipart/form-data'
}
}
).then( (response) => {
if (response.data.status === 'success') {
window.location.href = response.data.url;
}
}).catch(error => {
console.log("ERRRR:: ", error.response.data);
});
}
},
mounted() {
if (localStorage.title) {
this.title = localStorage.title;
}
if (localStorage.path) {
this.path = localStorage.path;
}
if (localStorage.transcript) {
this.transcript = localStorage.transcript;
}
const wavesurfer = WaveSurfer.create({
container: '#waveform',
waveColor: 'violet',
progressColor: 'purple',
scrollParent: true,
plugins: [
RegionPlugin.create({
dragSelection: true
}),
TimeLine.create({
container: '#wave-timeline'
})
]
});
wavesurfer.load('../storage/preprocessed-audio/' + this.path);
let play = false;
wavesurfer.on('region-click', (region, e) => {
e.stopPropagation();
// Play on click, loop on shift click
if (play) {
wavesurfer.pause();
play = false;
} else {
region.play();
play = true;
}
// console.log(this.form.title);
this.copyValues(region.start, region.end);
});
wavesurfer.on('region-created', (region, e) => {
console.log(region.id.substring(10))
let regionNode = document.createElement("div")
regionNode.className = "region"
let regionTitle = document.createElement("div")
regionTitle.className = "regionTitle"
regionTitle.innerHTML = region.id
regionTitle.style.fontWeight = "bold"
regionNode.appendChild(regionTitle)
let color = () => Math.random() * 256 >> 0;
let col = `${color()}, ${color()}, ${color()}`
regionTitle.style.color = 'rgb('+col+')';
region.color = 'rgba('+ col + ', 0.1)';
let copyButtonDiv = document.createElement("div")
copyButtonDiv.className = "copyTextButton"
let copyButton = document.createElement("Button")
copyButton.className = "inline-flex items-center px-4 py-2 bg-gray-800 border border-transparent rounded-md font-semibold text-xs text-white uppercase tracking-widest hover:bg-gray-700 active:bg-gray-900 focus:outline-none focus:border-gray-900 focus:ring focus:ring-gray-300 disabled:opacity-25 transition"
let copyButtonText = document.createTextNode("Copy Marked Text")
copyButton.appendChild(copyButtonText)
copyButton.addEventListener('click', this.getText)
let cpBtnType = document.createAttribute("type")
cpBtnType.value = "button"
copyButton.setAttributeNode(cpBtnType)
copyButtonDiv.appendChild(copyButton)
regionNode.appendChild(copyButtonDiv)
let newTranscriptDiv = document.createElement("div")
newTranscriptDiv.className = "pp_new_transcript flex flex-col"
let newTransLabel = document.createElement("label")
newTransLabel.innerText = "New Transcript:"
newTransLabel.style.fontWeight = "bold"
let selectTextArea = document.createElement("textarea")
selectTextArea.id = "selectedText"
selectTextArea.className = "selectedTextInput h-full"
let selectTextAreType = document.createAttribute("rows")
selectTextAreType.value = "5"
selectTextArea.setAttributeNode(selectTextAreType)
newTranscriptDiv.appendChild(newTransLabel)
newTranscriptDiv.appendChild(selectTextArea)
regionNode.appendChild(newTranscriptDiv)
let startStopDiv = document.createElement("div")
startStopDiv.className = "pp_start-stop"
let startLabel = document.createElement("label")
startLabel.innerText = "Start:"
startLabel.style.fontWeight = "bold"
let startLabelType = document.createAttribute("for")
startLabelType.value = "start"
startLabel.setAttributeNode(startLabelType)
let startInput = document.createElement("input")
startInput.id = "start"
let startInputType = document.createAttribute("disabled")
startInput.setAttributeNode(startInputType)
let stopLabel = document.createElement("label")
stopLabel.innerText = "Stop:"
stopLabel.style.fontWeight = "bold"
let stopLabelType = document.createAttribute("for")
stopLabelType.value = "stop"
stopLabel.setAttributeNode(stopLabelType)
let stopInput = document.createElement("input")
stopInput.id = "stop"
let stopInputType = document.createAttribute("disabled")
stopInput.setAttributeNode(stopInputType)
startStopDiv.appendChild(startLabel)
startStopDiv.appendChild(startInput)
startStopDiv.appendChild(stopLabel)
startStopDiv.appendChild(stopInput)
regionNode.appendChild(startStopDiv)
let submitBtnDiv = document.createElement("div")
submitBtnDiv.id = "submit_button"
let submitButton = document.createElement("Button")
let submitButtonText = document.createTextNode("Submit")
submitButton.className = "inline-flex items-center px-4 py-2 bg-gray-800 border border-transparent rounded-md font-semibold text-xs text-white uppercase tracking-widest hover:bg-gray-700 active:bg-gray-900 focus:outline-none focus:border-gray-900 focus:ring focus:ring-gray-300 disabled:opacity-25 transition"
submitButton.appendChild(submitButtonText)
submitBtnDiv.appendChild(submitButton)
regionNode.appendChild(submitBtnDiv)
// this.$set()
document.querySelector('#region_block').appendChild(regionNode)
})
let playButton = document.querySelector('#play');
let pauseButton = document.querySelector('#pause');
wavesurfer.on('play', function() {
playButton.style.display = 'none';
pauseButton.style.display = '';
});
wavesurfer.on('pause', function() {
playButton.style.display = '';
pauseButton.style.display = 'none';
});
playButton.addEventListener('click', function () {
wavesurfer.play()
})
pauseButton.addEventListener('click', function () {
wavesurfer.pause()
})
},
data() {
return {
title: '',
path: '',
transcript: '',
selectedText: '',
newTranscript: '',
start: '',
stop: ''
}
}
}
</script>
<style>
.audio_edit {
padding: 10px;
}
.pp_title, .pp_audio, .copyButton, .pp_transcript, .pp_new_transcript, .pp_start-stop, #wave-timeline, #submit_button {
padding-bottom: 10px;
}
.region {
border-top: 3px solid black;
border-bottom: 3px solid black;
padding-top: 3px;
margin-bottom: 3px;
}
.pp_new_transcript {
display: flex;
width: 100%;
}
.selectedTextInput {
-webkit-box-flex:1;
-webkit-flex:1;
-ms-flex:1;
flex:1;
border: none;
}
</style>
【问题讨论】:
-
@MichalLevý 我需要为每次需要动态创建代码块。我能想到 v-for 的唯一可能性是创建一个数组并在其中放置带有我需要的条目的对象。
-
是的,正是……
-
@MichalLevý 但问题之一是我无法动态分配 v-model 以进行 2 路绑定。 v-for 我只能用它来呈现数据,但我不需要创建输入字段。
标签: javascript forms vue.js vuejs3 inertiajs