How to associate one input to another(change one also change another) - vue.js

I am using vue 2.x via <script>.
I have a page contains a list of users, they are shown in a table and users can edit it:
name description1 description2
1st name input 1st description1 input 1st description2 input
2nd name input 2nd description1 input 2nd description2 input
....
For description1 and description2, they may contain a long content, but the input only show one line(I cannot use textarea here).
Therefore, I need to do:
If user click description1 input, there is a big popup dialog shown such that user can see the complete content and edit it in popup, after editing, if user click save button of popup, then the new content will be transferred to description1 input which user click;
If user click description2 input, there is a big popup dialog shown such that user can see the complete content and edit it in popup, after editing, if user click save button of popup, then the new content will be transferred to description2 input which user click;
and so on.
I have a main.jsp which includes student.html and the student.html as follows:
<div id="studentDiv">
<table>
<thead>
<tr>
<th>Name</th>
<th>Description1</th>
<th>Description2</th>
</tr>
</thead>
<tbody>
<tr v-for="s in studentList" :key="index">
<td><input v-model="s.name" /></td>
<td><input v-model="s.description1" /></td>
<td><input v-model="s.description2" /></td>
</tr>
</tbody>
</table>
<div class="modal fade" id="popupDialog" role="dialog"
aria-labelledby="modalLabel" aria-hidden="true">
<div class="modal-dialog modal-dialog-centered modal-xl modal-dialog- scrollable" role="document">
<div class="modal-body">
<textarea v-model="popupTextArea"></textarea>
</div>
</div>
</div>
<script>
studentVM = new Vue({
name:'student',
el: '#studentDiv',
data() {
return {
studentList:[],
popupTextArea: ''
}
},
......
})
</script>
</div>
popupDialog div is the popup dialog(bootstrap modal).
So how can I achieve my goal in Vue? How can I sync popup dialog value and input value of list student?

You can save the selected student + the property of the student you want to change, and apply the change when you click the save button:
data() {
return {
studentList:[],
popupTextArea: ''
selectedStudent: null,
selectedStudentProperty: '',
}
},
methods: {
selectStudent(student, property) {
this.selectedStudent = student;
this.selectedStudentProperty= property;
}
onPopupSave() {
this.selectedStudent[this.selectedStudentProperty] = this.popupTextArea;
// if the line above is not working reactively try using vue.set():
// this.$set(this.selectedStudent, this.selectedStudentProperty, this.popupTextArea)
}
}
<tr v-for="s in studentList" :key="index">
<td><input v-model="s.name" /></td>
<td><input v-model="s.description1" #click="selectStudent(s, 'description1')"/></td>
<td><input v-model="s.description2" #click="selectStudent(s, 'description2')"/></td>
</tr>

Related

How to clear dynamic values passed into vue-js-modal

In my vueJs project, i have a table that displays some products data from the database. When i click on a product tr, it should open a modal that displays a form to enter further details for the product clicked like so:
<table class="table table-responsive table-bordered">
<thead>
<tr>
<th>ID</th>
<th>Product Name</th>
<th>Action</th>
</tr>
</thead>
<tbody>
<tr v-for="prod in products" :key="prod.id">
<td>{{ prod.id }}</td>
<td>{{ prod.name }}</td>
<td><button class="btn btn-success btn-sm" #click.prevent="addStocks(prod)">Add Stock</button></td>
</tr>
</tbody>
</table>
Now in my script, i have a method to open the modal and pass the value of the item clicked to the modal like so;
addStocks(prod){
this.$modal.show('add-stocks')
this.newStock.unitPrice = prod.sellin_price
this.newStock.id = prod.id
this.newStock.name = prod.name
},
and my data object
data() {
return {
newStock: {
id: null,
name: '',
size: '',
srln: '',
colour: '',
mfg: '',
expiry: '',
selling_price: ''
},
}
}
and the modal component
<modal name="add-stocks" height="auto" :draggable="true" :width="600">
<div class="modal-header">
<h4>Add new stock</h4>
</div>
<div class="modal-body form-horizontal">
<div class="form-group">
<label for="unitPrice" class="control-label col-md-2">Unit Price</label>
<div class="col-md-4">
<div class="input-group">
<span class="input-group-addon" id="basic-addon1">₦</span>
<input class="form-control" v-model="newStock.unitPrice" readonly aria-describedby="basic-addon1">
</div>
</div>
<div style="clear:both"></div>
</div>
<div class="form-group">
//form fields here
</div>
<div class="modal-footer modal_btns">
<button class="btn btn-primary" #click.prevent="uploadStock">Save</button>
<button class="btn btn-danger" #click.prevent="cancelUpload">Cancel</button>
</div>
</modal>
Now, the issue is when i fill the fields in the modal and click on the cancel button (without saving), i expect the fields to be cleared so when i click on another product tr, i get a fresh form, but this is not the case, the details filled into the previously closed modal form displays. In the cancelUpload methods, i have cleared the fields before closing the modal;
cancelUpload(){
this.$modal.hide('add-stocks')
this.newStock.unitPrice = prod.sellin_price
this.newStock.id = prod.id
this.newStock.name = prod.name
}
When i click on the save button and after api call is made, i call this method to hide the modal but the same issue occurs as the details display when next i open another modal.
How do i fix this?
First of all check whether your method is called everytime the modal is being closed i.e either by clicking on cancel button,cross sign or esc key.
Next this could be the issue of vue reactivity.
An object property should be updated using set method in vue js to keep it reactive.
Hence try as below.
cancelUpload(){
this.$modal.hide('clear-stocks')
this.$set(this.newStock,unitPrice,'');
this.$set(this.newStock,id,'');
this.$set(this.newStock,name,'');
}
You can clear other properties also in the above method.
Or else in the addStocks method also you can set the rest of properties to empty.
More on Vue.set here.

Passing data from table row into bootstrap modals

I'm creating vue js spa and what i trying to create is when i click on table row, it will show a modals with/showing data from the row that i clicked on.
here i have created my table
<tr class="cursor-pointer" #click="modalContextMenu">
<td>
<img :src="'/images/artikel/' + props.item.images + 'n.jpg'" class="img-rounded img-sm" v-if="props.item.images">
<img :src="'/images/image-articlen.jpg'" class="img-rounded img-sm" v-else>
</td>
<td>{{props.item.name}}</td>
<td>{{props.item.category.name}}</td>
<td>{{props.item.writter}}</td>
<td v-html="$options.filters.checkStatus(props.item.publish)"></td>
<td v-html="$options.filters.checkStatus(props.item.featured)"></td>
<td>{{props.item.created_at | publishDate}}</td>
</tr>
at <tr> i put #click methods that make modal show and data that i want to show into modals is data from each <td> for that row / <tr>
right now my modalContextMenu methods is basically make modals visible/appear like this
modalContextMenu(){
this.modalShow= true;
}
You can create a data property for the data you want to show in the modal.
data () {
modalData: ''
}
Then you can set that property in onClick function.
HTML
<tr class="cursor-pointer" #click="modalContextMenu(data)">
<td>
<img :src="'/images/artikel/' + props.item.images + 'n.jpg'" class="img-rounded img-sm" v-if="props.item.images">
<img :src="'/images/image-articlen.jpg'" class="img-rounded img-sm" v-else>
</td>
<td>{{props.item.name}}</td>
<td>{{props.item.category.name}}</td>
<td>{{props.item.writter}}</td>
<td v-html="$options.filters.checkStatus(props.item.publish)"></td>
<td v-html="$options.filters.checkStatus(props.item.featured)"></td>
<td>{{props.item.created_at | publishDate}}</td>
</tr>
JS:
modalContextMenu(data) {
this.modalData = data;
this.modalShow= true;
}
Then access the data in modal using {{ modalData }}.

How to set header value in kendo grid row template

I am using jquery kendo grid in my project where i used row template to show three column in one row. Below is the code:
<table id="grid" style="width:100%">
<thead style="display:none">
<tr>
<th>
Details
</th>
</tr>
</thead>
<tbody>
<tr>
<td colspan="3"></td>
</tr>
<tr>
<td>
</td>
</tr>
</tbody>
</table>
<script id="rowTemplate" type="text/x-kendo-tmpl">
<div>
<span class="name" style="font-size:medium">#: FirstValue #</span>
<span class="name" style="font-size:medium">#: SecondValue #</span>
</div>
<tr>
<td style="width:30%">
#: GetName #
<span class="name" style="font-size:14px; color:green">#: Designation #</span>
<span class="name" style="font-family:Arial; font-size:small">#: Company #</span>
</td>
</tr>
</script>
in the above code i am just passing my model data it's working fine but when i added one div which have value firstName and LastName so it is also repeating with this data but i want to to show separately.How do i show it separately so that it should not repeat with grid.
there is one problem in your html template.
Please replace '#' with 'Javascript:void(0)'.
Error:- #: GetName #
Fix:- #: GetName #
Hope that's work for you.
http://jsfiddle.net/parthiv89/t0w3ht6m/1/
if you like then don't forget to like.
I got solution by own, Firstly i changed code in my schema like this:
schema: {
parse: function (data) {
var items = [];
for (var i = 0; i < data.data.length; i++) {
if (data.data[i].CorrectValue != null && data.data[i].SearchValue != null) {
$("#spnSR")[i].innerHTML = "<b>"+"Get results for this text: "+"</b>"+data.data[i].CorrectValue;
$("#spnSV")[i].innerHTML = "<b>" + "Searched for this text: " +"</b>" + data.data[i].SearchValue;
}
}
var product = {
data: data.data,
total: data.total
};
items.push(product);
return (items[0].data);
},
}
Then in html i used two span to show this value which is there in for loop.
and it's working fine for me.
Thanks everyone.

How to handle variable number of process variables in Camunda

I'm new to Camunda and didn't find any tutorial or reference explaining how to achieve the following:
When starting a process I want the user to add as many items as he likes to an invoice. On the next user task all those items and their quantity should be printed to somebody approving the data.
I don't understand yet how to get this 1:n relationship between a process and its variables working. Do I need to start subprocesses for each item? Or do I have to use a custom Java object? If so, how can I map form elements to such an object from within the Tasklist?
I got it working with the help of the links provided by Thorben.
The trick is to use JSON process variables to store more complex data structures. I initialize such lists in my "Start Event". This can be done either in a form or in my case in a Listener:
execution.setVariable("items", Variables.objectValue(Arrays.asList(dummyItem)).serializationDataFormat("application/json").create());
Note that I added a dummyItem, as an empty list would lose its type information during serialization.
Next in my custom form I load this list and can add/remove items. Using the camForm callbacks one can persist the list.
<form role="form" name="form">
<script cam-script type="text/form-script">
/*<![CDATA[*/
$scope.items = [];
$scope.addItem = function() {
$scope.items.push({name: '', count: 0, price: 0.0});
};
$scope.removeItem = function(index) {
$scope.items.splice(index, 1);
};
camForm.on('form-loaded', function() {
camForm.variableManager.fetchVariable('items');
});
// variables-fetched is not working with "saved" forms, so we need to use variables-restored, which gets called after variables-fetched
camForm.on('variables-restored', function() {
$scope.items = camForm.variableManager.variableValue('items');
});
camForm.on('store', function() {
camForm.variableManager.variableValue('items', $scope.items);
});
/*]]>*/
</script>
<table class="table">
<thead>
<tr><th>Name</th><th>Count</th><th>Price</th><th></th></tr>
</thead>
<tbody>
<tr ng-repeat="i in items">
<td><input type="text" ng-model="i.name"/></td>
<td><input type="number" ng-model="i.count"/></td>
<td><input type="number" ng-model="i.price"/></td>
<td>
<button class="btn btn-default" ng-click="removeItem($index)">
<span class="glyphicon glyphicon-minus"></span>
</button>
</td>
</tr>
</tbody>
<tfoot>
<tr>
<td colspan="4">
<button class="btn btn-default" ng-click="addItem()">
<span class="glyphicon glyphicon-plus"></span>
</button>
</td>
</tr>
</tfoot>
</table>
</form>
Two things aren't working yet:
Field validation, e.g. for number fields
The dirty flag used on the "save" button doesn't get updated, when adding/removing rows

How do I implement something like this?

Well I have to implement something as follows:
I need to display a list of Contact IDs of all the contacts I have in my model.
<ul>
#for (int i = 0; i < Model.Contacts.ToList().Count; i++)
{
<li><a onclick="showContactInfoDialog(#Model.Contacts.ToList()[i].ContactId)">Model.Contacts.ToList()[i].ContactId</a></li>
}
</ul>
Each list element will be clickable, upon clicking which, a dialog will popup.
function showContactInfoDialog(id) {
document.getElementById('contact-dialog').style.display = 'block';
}
The dialog should show that particular contact's First Name, Last Name, Title, Email.
<div id="contact-dialog">
<form action="Contact/SaveContactEdits" method="post">
<table>
<tr>
<td>First Name</td>
<td>
<input type="text" name="FName"value="#Model.Contacts.ToList()[id].FirstName" /></td>
</tr>
<tr>
<td>Last Name</td>
<td>
<input type="text" name="LName" value="#Model.Contacts.ToList()[id].LastName" /></td>
</tr>
<tr>
<td>Title</td>
<td>
<input type="text" name="Title" value="#Model.Contacts.ToList()[id].Title" /></td>
</tr>
<tr>
<td>Email Address</td>
<td>
<input type="text" name="Email" value="#Model.Contacts.ToList()[id].Email" /></td>
</tr>
</table>
<input type="submit" value="Save"/>
</form>
</div>
The dialog should let user make edits to the contact's details.
How do I do this? I'm having problem in passing the 'id' parameter to the dialog box element.
<div id="contact-dialog">
I'm having problem in passing the 'id' parameter to the dialog box
element.
The way you are using the id is not correct as you use it like the following. In the given code below (taken from your code) you are using the id as the index and that won't work most of the time especially if the ids does not start with 0.
Model.Contacts.ToList()[id]
That also won't work because the onclick event happens on the client side where the model is no longer available. So what you can do, since calling another controller method is not an option is to write all the details in a hidden field. Put them on a single container, for example one div per contact, the assign the id of the contact to the div. When the a tag is clicked, you read the values from the div and assign them to the form. All of this can be handled easier with tools like knockout, but if using it is not an option then here's the code that will do the trick.
// in your loop do this
// btw, it would be better if you Contacts object is an IList so you can do indexing easier
<li><a onclick="showContactInfoDialog(#Model.Contacts.ToList()[i].ContactId)">Model.Contacts.ToList()[i].ContactId</a>
<div id="#("contactrow"+Model.Contacts.ToList()[i].ContactId)">
#Html.HiddenFor(m=>Model.Contacts.ToList()[i].FirstName)
// do the same for the rest of the fields you want to show on the dialog
</div>
</li>
before you show the dialog, copy the contents to the form:
function showContactInfoDialog(id) {
// we are targetting this -> <input type="text" name="FName"
// assign an id (fname) for optimal performance
var container = $("#contactrow"+id);
        $("#fname").val(container.find('#FirstName').val());
// do the same for the rest of the fields
document.getElementById('contact-dialog')
.style.display = 'block';
}