How to use reference in vuejs 3 inside for loop - vuejs3

I've been developing my first project with Vue3 js.I have tried to implement vue-signature pad inside for loop.I thnik vue signature pad is working based on ref. I have done vue-signature pad with out loop. But i dont know how to use ref inside loop. Anybody please help how to implement signature pad inside loop using vue3. Thank you in advance.
<template>
<div
class="row"
v-for="(applicants, index) in applicant_details"
:key="index"
>
<div class="col-sm-4">
<div class="form-group">
<p>Signature for {{ applicants.first_name }}</p>
</div>
</div>
<div class="col-sm-4">
<div class="form-group">
<VueSignaturePad ref="" />
<button type="button" #click="undo1" class="btn btn-warning">
Undo
</button>
</div>
</div>
<div class="col-sm-2" style="margin-top: 40px; text-align: center">
<div class="form-group">
<button type="button" #click="undo" class="btn btn-danger">
Clear
</button>
</div>
</div>
<div class="col-sm-2">
<div class="form-group">
<button type="button" #click="save_signature" class="btn btn-success">
Save
</button>
</div>
</div>
</div>
</template>
<script>
export default {
data() {
return {
applicant_details: [
{ first_name: 'john', signature: '' },
{ first_name: 'david', signature: '' },
],
};
},
methods: {
undo() {
//will undo the signature
},
save_signature() {
//Save the signature
},
},
};
</script>

Be carefull, you have some issue with your code to begin with.
No template for you html
export default not well formated
List item
You original issue may be in --> v-for="(applicants, index) in 'applicant_details'"
Here it loop on the STRING 'applicant_details'. If you want to loop on a variable in your data juste use applicant_details.
U can also use vite.new/vue to create reproductive code and help us to help you.
Here is the corrected code : https://stackblitz.com/edit/vitejs-vite-9kvde4?file=src%2FApp.vue&terminal=dev

Related

Vue3 can only modify first element in an array when inside a modal

I am new to using Vue3 (composition API) with bootstrap 5 and came across a problem:
When I render a list, and pass each element as a prop as so:
<div :key="item.id" v-for="item in items">
<EditItem :item="item"/>
</div>
I can modify the props values just fine inside of EditItem.vue (the props are JSON objects), but when I am inside a modal I can only modify the values for the 1st index. My code looks something like this:
<script setup>
defineProps({
item: {
type: Object,
required: true
},
})
</script>
<template>
<!-- Let's me edit all items in list just fine -->
<input type='text' v-model="item.name">
<div> {{item.name}} </div>
<button type="button" class="btn btn-primary" data-bs-toggle="modal" data-bs-target="#exampleModal">
Edit Item
</button>
<!-- Modal -->
<div class="modal fade" id="exampleModal" tabindex="-1" aria-labelledby="exampleModalLabel" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h1 class="modal-title fs-5" id="exampleModalLabel">Modal title</h1>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body">
<div class="mb-3">
<!-- Will only let me edit the first indexed list item -->
<label for="name" class="form-label">Item name</label>
<input type='text' class="form-control" id="name" placeholder="John Doe" v-model="item.name">
<div> {{ item.name }} </div>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Close</button>
<button type="button" class="btn btn-primary">Save changes</button>
</div>
</div>
</div>
</div>
</template>
I think this happens due to the modal being treated as a different document/context so vue3 re-renders everything, so the indexing restarts from 1. I am not sure how to fix this issue, any help is appreciated. Thanks
Edit:
My problem is similar to the issue described in this question: How to show fresh bootstrap modal data when using Vue.js
However, it hasn't been answered properly and is from 2018
Edit 2:
Solved:
It was a simple fix, simply take the modal out of the v-for loop. Only have the button inside the loop. And yes, I realize you cannot edit the values of a prop inside of a child component. I simplified the code, as the code with the form I have is quite long due to the many fields in my JSON objects.
Props are readonly. To be able to edit array, you need to emit delete function where you have this array. Your "Lets me edit all items" not working too. It just edits a local variable, not an array.
This is how you make reusable form:
form.vue
<template>
<form #submit.prevent="$emit('onSubmit', data)">
<input type="text" v-model="data.name" />
<button type="submit">Save</button>
</form>
</template>
<script setup>
const props = defineProps({ item: { type: Object, required: true }})
const data = reactive(props.item)
defineEmits(['onSubmit'])
</script>
parent.vue
<template>
<form :item="item" #on-submit="editItem"></form>
</template>
<script setup>
function editItem(data) {
// Edit array here.
}
</stript>

Vue Vite Webpack doesn't compile the background image

I'm using VUE Vite and Webpack to compile the files. My problem is the following:
If i set my background image for the body tag in css then I can see the background in the develper verson in the browser. After creating the webpack files it won't use the background.
It seems like it doesnt compile the background. Does anyone know why this issue happens?
I appreciate any kind of help and suggestions.
My Folder structure is the following:
Code:
<template>
<div class="d-flex align-items-center justify-content-center vh-100">
<form>
<div class="mb-3">
<input type="email" class="form-control input-style-1" placeholder="Email eingeben" v-model="email">
</div>
<div class="mb-3">
<input type="password" class="form-control input-style-1" placeholder="Passwort eingeben" v-model="password">
</div>
<div class="d-grid">
<button class="btn btn-primary button-style-1" type="button" #click="login">Einloggen</button>
</div>
<div class="d-grid">
<router-link class="text-white mt-3" to="/register">Neuen Account erstellen</router-link>
</div>
</form>
</div>
</template>
<script>
export default {
name: 'Login',
data: function() {
return {
email: '',
password: ''
}
},
methods: {
async login(){
if(this.email == "" || this.password == "") return;
await window.rpc.callServer("sLoginUser", [this.email, this.password]);
}
}
}
</script>
<style>
body {
background: url("./images/background.jpg") !important;
}
</style>

Converting Semantic-Ui-React to Semantic-UI; event handler

I am trying to successfully express Semantic-UI code with the same functions I have used in Semantic-UI-react code. Any help would be appreciated.
This is what I have:
class Preview extends React.Component {
componentDidMount() {
const update = () => {
this.dest.textContent = this.src.innerHTML.replace(/</g,
'\n<');
};
setInterval(update, 300);
update();
}
render() {
return (
<div>
<div ref={(src) => Object.assign(this, { src })}>
<Demo />
</div>
<pre ref={(dest) => Object.assign(this, { dest })}>
</pre>
</div>
)
}
}
export class Demo extends Component { constructor(){
super();
this.localStorageClear.bind(this); }
localStorageClear = (e) => {
e.preventDefault();
window.localStorage.clear();
};
render() {
return (
<div id = "soundcloud-player">
<Container className='col'>
<div className='col-left js-playlist toggle'>
<div className='inner'>
</div>
</div>
<div className='col-right'>
<div className = 'main'>
<Input size='massive' icon='search' input = {{ className:
'input-search js-search' }} placeholder='Search for a song
or artist...'/>
<Icon className='js-submit'/>
<Button onClick={(e) => this.localStorageClear(e)}
className='clear' content='Clear Playlist'/>
<Button content='Show/Hide Playlist' id='toggle'
className='hide-toggle'/>
<Card className='js-search-results search-results'/>
</div>
</div>
</Container>
</div>
The code written in the Preview Component is specifically written to convert the code written inside of the Demo Component. The Demo Component should convert to what is shown below:
<div class="ui container col">
<div class="col-left js-playlist toggle">
<div class="inner">
</div>
</div>
<div class="col-right">
<div class="main">
<div class="ui massive icon input">
<input placeholder="Search for a song or artist..." class="js-search input-search">
<i class="search icon js-submit"></i>
</div>
<button onclick="localStorageClear();" class="clear">Clear Playlist</button>
<button class="hide-toggle" href="#" id="toggle">Show/Hide Playlist</button>
<div class="search-results js-search-results ui cards">
</div>
</div>
</div>
The actual output of the code at the top is:
<div id="soundcloud-player">
<div class="ui container col">
<div class="col-left js-playlist toggle">
<div class="inner">
</div>
</div>
<div class="col-right">
<div class="main">
<div class="ui massive icon input input-search">
<input placeholder="Search for a song or artist..." type="text">
<i aria-hidden="true" class="search icon">
</i>
</div>
<i aria-hidden="true" class="icon js-submit">
</i>
<button class="ui button clear" role="button">Clear Playlist
</button>
<button id="toggle" class="ui button hide-toggle" role="button">Show/Hide Playlist
</button>
<div class="ui card js-search-results search-results">
</div>
</div>
</div>
</div>
</div>
I'm trying to figure out why the localStorageClear function does not show up for the first button in the actual output. Is there wrong I am doing at the top inside of the Semantic-UI-React code inside of the Demo Component?
The way you are setting up your handler function is not correct. You are also binding in your constructor AND inline with an arrow function inside of the onClick event for the button. You only need to bind in one place.
Take a look at the codesandbox example I made so you can see how to declare a class method handler function and use it with a click event. Notice that there is no constructor here or arrow function to bind on the onClick event? That is because the binding is happening on the class method. handleClick = () => {}
class App extends React.Component {
handleClick = e => {
console.log(e.target + " was clicked.");
// Do whatever functionality you need here.
// In your example you do not show that it matters what the element is,
// so you don't need to pass the event (e) into your class method.
};
render() {
return (
<Container>
<Divider hidden />
<Button content="Click Me" onClick={this.handleClick} />
<Divider hidden clearing />
<Message info>
Look in your console and you will see that the click function is
working.
</Message>
</Container>
);
}
}
Here is a working codesandbox example.

How to develop search suggestion text box using angular 2/4

I'am new in Angular. How can i develop a drop down suggestion search box in angular 2/4. when clicking on search button the details are shown using below codes.But am trying while typing on text box the suggestion details need to show. same like Auto complete (During searching, ‘as-you-type’ suggestion to be displayed.)
component.HTML
<form role="form">
<div class="row">
<div class="form-group">
<div class="input-group">
<input name="search"
class="form-control"
type="text"
placeholder="Search"
required="" [(ngModel)]='searchcontent'>
<span class="input-group-btn">
<button
class="btn btn-success ProductSearchBtn"
type="button"
(click)='FetchItemDetailsSearch(searchcontent)'>
<i class="glyphicon glyphicon-search"
aria-hidden="true"></i>
<span style="margin-left:10px;">Search</span>
</button>
</span>
</div>
</div>
</div>
</form>
</div>
</section>
<section class="CommonsubWhiteBg"
style='height:850px;overflow-y:scroll; overflow-x:hidden'
(scroll)="onScroll($event)">
<ng-container *ngFor="let item of itemdetails;">
<article class="row" style="margin:0px;">
<div class="col-md-12 col-sm-12 col-xs-12 EnquiryMore">
<a [routerLink]="['/productdetails',item.ItemID]">
<h5>{{item.ItemCode + ' - ' + item.ItemDescription}}</h5>
</a>
</div>
</article>
</ng-container>
<ng-container *ngIf="!itemdetails" style="margin:0px;">
<article class="col-md-12">
<h3>Loading data...</h3>
</article>
</ng-container>
<ng-container *ngIf="itemdetails&&itemdetails.length==0"
class="ItemNotfoundArea row" style="margin:0px;">
<article class="col-md-12">
<h1>Sorry</h1>
<p>Item Not Found</p>
</article>
</ng-container>
</section>
component.ts file
FetchItemDetailsSearch(itemcodeordesc: string): void {
this.pageIndex = 1;
this.searchflag = 1;
if (itemcodeordesc.length > 0)
this.searchcontent = itemcodeordesc;
else {
itemcodeordesc = undefined
this.searchcontent = itemcodeordesc;
}
this.prevScrollPosition = 0;
this._enqService
.FetchItemDetailsSearch(this.searchcontent, this.pageIndex)
.subscribe(itemsData => this.itemdetails = itemsData,
error => {
console.error(error);
this.statusMessage =
"Problem with the service.Please try again after sometime";
}
);
}
**Service.ts **
FetchItemDetailsSearch(itemcodeordesc: string, pageIndex: number):
Observable<IEnquiryDetails[]> {
return this._http.get('http://localhost:1234/api/enquirydetails/',
{ params:
{ itemcodeordesc: itemcodeordesc,
pageIndex: pageIndex }
})
.map((response: Response) => <IEnquiryDetails[]>response.json())
.catch(this.handleError)
}
condition: trying only with Angular 4/2 not jQuery
Take a look at angular material auto complete component.
https://material.angular.io/components/autocomplete/examples.
You can also have your own custom filter function. Below sample code would give you a way out to achieve the same.
https://stackblitz.com/angular/krlrmgepmrv?file=app%2Fautocomplete-filter-example.ts
or
Try this
http://www.angulartutorial.net/2017/03/simple-search-using-pipe-in-angular-2.html
Please check this answer
<form role="form">
<div class="row">
<div class="form-group">
<div class="input-group">
<input name="search" class="form-control" type="text" placeholder="Search" (keyup)="FetchItemDetailsSearch(searchcontent)" [(ngModel)]="searchcontent">
<span class="input-group-btn">
<button class="btn btn-success ProductSearchBtn" type="button" (click)='FetchItemDetailsSearch(searchcontent)'><i class="glyphicon glyphicon-search" aria-hidden="true"></i><span style="margin-left:10px;">Search</span></button>
</span>
</div>
</div>
</div>
</form>
You can use auto complete plugin like this .

trumbowyg editor with vuejs

I am using the trumbowyg editor control in my vuejs spa. From the documentation I know that I can use the following code to set the contents of the editor.
$('#editor').trumbowyg('html','<p>Your content here</p>');
$('#editor').trigger('tbwchange');
However, it is not working for me in my VueJs App. I have an object that has a description key defined. I can console.log the description , but when I try to assign it to the editor control as mentioned above, it fails . I can see no error in the console but the text just won't show up in the editor.
Here is what I am going at the moment.
<template>
<div class="modal fade" data-backdrop="static" data-keyboard="false">
<div class="modal-dialog modal-lg">
<div class="modal-content">
<div class="modal-header">
<h4 class="modal-title">
<span v-if="anouncement">Edit Anouncement</span>
<span v-else>New Anouncement</span>
</h4>
</div>
<div class="modal-body">
<div class="form-group">
<input type="text" placeholder="enter anouncement summary here" class="form-control" v-model="anouncementObj.summary">
</div>
<div class="form-group">
<input type="text" placeholder="enter location here" class="form-control" v-model="anouncementObj.location">
</div>
<textarea class="note-view__body" id="anonDescription" v-model="description" placeholder="enter event description"></textarea>
</div>
<div class="modal-footer">
<button type="button" v-on:click="clear()" class="btn btn-link" data-dismiss="modal">Close</button>
<button type="button" v-on:click="performSave()" class="btn btn-link">Save</button>
</div>
</div>
</div>
</div>
</template>
<script>
export default {
props : {
anouncement : Object
},
data() {
return {
anouncementObj :{}
}
},
mounted () {
this.makeTextBoxReady();
this.anouncementObj = Object.assign({},this.anouncementObj, this.anouncement || {});
$('#anonDescription').trumbowyg('html',this.anouncement.description);
$('#anonDescription').trigger('tbwchange');
console.log(this.anouncement.description);
},
methods : {
makeTextBoxReady: function() {
$(document).ready(function() {
if (!$('html').is('.ie9')) {
if ($('.note-view__body')[0]) {
$('.note-view__body').trumbowyg({
autogrow: true,
btns: [
'btnGrp-semantic', ['formatting'],
'btnGrp-justify',
'btnGrp-lists', ['removeformat']
]
});
}
}
});
},
performSave : function() {
let description = $('#anonDescription').trumbowyg('html');
let formData = new FormData();
for (name in this.anouncementObj) {
formData.append(name, this.anouncementObj[name]);
}
if( !this.anouncementObj.id) {
this.anouncementObj.id = 0;
}
formData.append('description',description);
this.$http.post('/admin/anouncement/createOrUpdate', formData).then(response => {
// console.log(response);
if(response.data.status==200) {
alert(response.data.message);
this.$emit('getAnouncements');
}
})
},
clear: function() {
this.anouncementObj= {};
}
}
}
</script>
Can you please let me know what I am doing wrong here? I have also tried the nexttick approach but even that is not working.
I got it working. I was not using the correct bootstrap modal id. Please see this related question for more information.
This is the correct code.
if(this.anouncementObj && this.anouncementObj.description && this.anouncementObj.id) {
$('#'+this.anouncementObj.id+' #anonDescription').trumbowyg('html',this.anouncementObj.description);
$('#'+this.anouncementObj.id+' #anonDescription').trigger('tbwchange');
}

Resources