How can I bind multiple values from array in v-model for form-input on vue.js? - vue.js

I need to show full address in one form-input with buttons 'Edit' and 'Delete', so it's working, but in browser console I have error for all addresses like this
'[Vue warn]: Error in event handler for "input": "TypeError: Cannot use 'in' operator to search for 'zip' in 'Country Name', 'City', 'Street Address', [object Object]"'
My vue code:
<template>
<div>
....
</div>
...
<form class="form-inline" >
<div class="form-row col-md-6" v-for="address in addressList">
<b-form-group>
<b-form-input class="form-control mb-2 mr-sm-2" id="address.id" v-model="address.countryName + ', ' + address.city + ', ' + address.streetAddress + ', ' + address.zip" />
</b-form-group>
<div class="btn-group mr-2" role="group">
<button type="button" class="btn btn-secondary mb-2">Edit</button>
<button type="button" class="btn btn-secondary mb-2">Delete</button>
</div>
</div>
</form>
</b-form>
</div>
</template>
<script>
...
data() {
return {
addressList: [],
}
},
async beforeRouteEnter(to, from, next) {
next(async (c) => await c.initData());
},
methods: {
async initData() {
await this.loadAddressList();
},
async loadAddressList() {
this.addressList = await accountService.getAddressList();
},
}
}
</script>
I don't understand why I am getting this error but it's working. Is there another better solution for this? And without error?
v-model="address.countryName + ', ' + address.city + ', ' + address.streetAddress + ', ' + address.zip"

I think your problem lays with binding the v-model. How you have it, it binds/concats multiple variables which isn't the intended use for v-modal.
If you only want to display the value, you could try changing:
v-model="address.countryName + ', ' + address.city + ', ' + address.streetAddress + ', ' + address.zip"
to
:value="address.countryName + ', ' + address.city + ', ' + address.streetAddress + ', ' + address.zip"

Related

How do you get data and bind to a table?

I am trying to get data from a database and just bind the output to a table. I am using AJAX because some of my other codes won't allow me to mix with the IEnumerable. It doesn't seem to run the command and never trips breakpoints... Not sure what I might be doing wrong. I have scoured the internet and can't seem to find a solution or anything close, just broken code. It is loading the JS and even if I reference JS it still has the same behavior...
Index
#model Rabbit.Application.Models.Onboarding.Client
#{
ViewBag.Title = "Index";
Layout = "~/Areas/Onboarding/Views/Shared/_Layout.cshtml";
}
<h2> Clients</h2>
<button type="button" class="btn btn-primary" data-toggle="modal" data-target="#myModal" onclick="OpenAddPopup();">Add New Client</button><br /><br />
<fieldset>
<table table id="tblClient" class="table">
<thead>
<tr>
<th>companyName</th>
<th>PhoneNo</th>
<th>ContactPerson</th>
<th>Email</th>
<th>Address</th>
<th></th>
</tr>
</thead>
<tbody class="tbody">
</tbody>
</table>
</fieldset>
<script type="text/javascript">
//Load Data in Table when documents is ready
$(document).ready(function () {
$.ajax({
url: "/Clients/GetAllClients",
type: "GET",
contentType: "application/json;charset=utf-8",
dataType: "json",
success: function (result)
{
console.log(data);
if (result) {
//itetrate thorugh each record and bind it to td
var html = '';
$.each(result, function (key, item) {
html += '<tr>';
html += + '<td>' + item.companyName + '</td>'
html += + '<td>' + item.PhoneNo + '</td>'
html += + '<td>' + item.ContactPerson + '</td>'
html += + '<td>' + item.Email + '</td>'
html += + '<td>' + item.Address + '</td>'
html += +'</tr>';
});
$('#tbody').html(html);
},
error: function (errormessage) {
alert(errormessage.responseText);
}
});
}
</script>
Controller
public IActionResult Index()
{
return View();
}
public JsonResult GetAllClients()
{
var clientlist = (from client in _context.Client
select client).ToList();
return Json(clientlist);
}
After I tested it, it seems that this is just your grammar problem.
First,if you don't have a data variable,you need to delete console.log(data);.
Second,you should change html += + '<td>' + item.companyName + '</td>' to html += '<td>' + item.companyName + '</td>'.The same is true for the following, remove the + behind the =.
Third,you should change $('#tbody').html(html); to $('.tbody').html(html);,because you are using class="tbody".And you need to add a } after this,and add ) after the last one }.Because overall you are missing a } and a ).
Fourth,if $(document) reports an error, you can add <script src="https://code.jquery.com/jquery-1.12.4.js" type="text/javascript"></script> before <script type="text/javascript">.
Below is my test code,it works fine:
#model BindTable.Models.Client
<h2> Clients</h2>
<button type="button" class="btn btn-primary" data-toggle="modal" data-target="#myModal" onclick="OpenAddPopup();">Add New Client</button><br /><br />
<fieldset>
<table table id="tblClient" class="table">
<thead>
<tr>
<th>companyName</th>
<th>PhoneNo</th>
<th>ContactPerson</th>
<th>Email</th>
<th>Address</th>
<th></th>
</tr>
</thead>
<tbody class="tbody">
</tbody>
</table>
</fieldset>
<script src="https://code.jquery.com/jquery-1.12.4.js" type="text/javascript"></script>
<script type="text/javascript">
//Load Data in Table when documents is ready
$(document).ready(function () {
$.ajax({
url: "/Client/GetAllClients",
type: "GET",
contentType: "application/json;charset=utf-8",
dataType: "json",
success: function (result)
{
if (result) {
//itetrate thorugh each record and bind it to td
var html = '';
$.each(result, function (key, item) {
html += '<tr>';
html += '<td>' + item.companyName + '</td>'
html += '<td>' + item.phoneNo + '</td>'
html += '<td>' + item.contactPerson + '</td>'
html += '<td>' + item.email + '</td>'
html += '<td>' + item.address + '</td>'
html += '</tr>';
});
$('.tbody').html(html);
}
},
error: function (errormessage) {
alert(errormessage.responseText);
}
});
})
</script>
Test Result:

How to rotate single chevron on accordion in vue?

I am using vue chevron in accordion inside for loop. When I am clicking a single dropdown, all other chevrons are rotating. How to rotate the specific chevron for the clicked dropdown in vue ? I am using vue chevron package from https://ispal.github.io/vue-chevron/ . My dropdown looks like this -
My vue code:
<div class="accordion" id="accordionExample">
<div
v-for="(data, index) in topicList"
:key="index"
class="card"
>
<div class="card_header" id="headingOne">
<h2 class="mb-0">
<div
class="btn btn-topic example text-left collapsed"
#click="toggle"
type="button"
data-toggle="collapse"
:data-target="'#collapseOne' + index"
aria-expanded="true"
aria-controls="collapseOne"
>
<vue-chevron
:point-down="pointDown"
:duration="duration"
:thickness="thickness"
:angle="angle"
:round-edges="roundEdges"
/>
{{ data.title }}
</div>
</h2>
</div>
<div
:id="'collapseOne' + index"
class="collapse"
aria-labelledby="headingOne"
data-parent="#accordionExample"
>
<div class="card-body">
<ul
v-for="(data, index) in topicList[index].lessons"
:key="index"
#click="getContent(data.lessonId)"
class="list-group py-1"
>
<li class="list-group-item list-style">
{{ data.title }}
</li>
</ul>
</div>
</div>
</div>
</div>
<script>
import VueChevron from "vue-chevron"
export default{
components:{ VueChevron }
data(){
return{
pointDown: false,
thickness: 8,
duration: 500,
angle: 40,
roundEdges: true,
easing: function n(t) {
return t;
}
}
methods: {
toggle() {
this.pointDown = !this.pointDown;
},
}
}
courseAccess() {
this.$axios
.get(this.$api + "api/v1/courses/" + this.courseId, {
headers: {
Authorization: "Bearer " + localStorage.getItem("_utoken"),
},
})
.then((response) => {
// this.topicList = response.data.data.topics.map((element) => {
// return { ...element, pointDown: true };
// });
this.topicList = response.data.data.topics
this.firstTopic = response.data.data.topics[0].lessons[0].lessonId;
this.getFirstContent(this.firstTopic);
this.loadTopics = true;
});
},
All vue-chevron are binding there point-down prop to the same boolean. You could try to use an array of boolean instead and change your toggle method.
<div class="accordion" id="accordionExample">
<div
v-for="(data, index) in topicList"
:key="index"
class="card"
>
<div class="card_header" id="headingOne">
<h2 class="mb-0">
<div
class="btn btn-topic example text-left collapsed"
#click="toggle(index)"
type="button"
data-toggle="collapse"
:data-target="'#collapseOne' + index"
aria-expanded="true"
aria-controls="collapseOne"
>
<vue-chevron
:point-down="pointDown[index]"
:duration="duration"
:thickness="thickness"
:angle="angle"
:round-edges="roundEdges"
/>
{{ data.title }}
</div>
</h2>
</div>
<div
:id="'collapseOne' + index"
class="collapse"
aria-labelledby="headingOne"
data-parent="#accordionExample"
>
<div class="card-body">
<ul
v-for="(data, index) in topicList[index].lessons"
:key="index"
#click="getContent(data.lessonId)"
class="list-group py-1"
>
<li class="list-group-item list-style">
{{ data.title }}
</li>
</ul>
</div>
</div>
</div>
</div>
<script>
import VueChevron from "vue-chevron"
export default{
components:{ VueChevron }
data(){
return{
pointDown: [],
thickness: 8,
duration: 500,
angle: 40,
roundEdges: true,
easing: function n(t) {
return t;
}
}
methods: {
toggle(index) {
this.pointDown[index] = !this.pointDown[index];
},
}
}
EDIT
The problem discussed in the comments could be caused by reactivity issues. To solve these we are trying to initialize pointDown with an array of the correct size.
courseAccess() {
this.$axios
.get(this.$api + "api/v1/courses/" + this.courseId, {
headers: {
Authorization: "Bearer " + localStorage.getItem("_utoken"),
},
})
.then((response) => {
// this.topicList = response.data.data.topics.map((element) => {
// return { ...element, pointDown: true };
// });
this.topicList = response.data.data.topics;
this.pointDown = new Array(this.topicList.length).fill(false);
this.firstTopic = response.data.data.topics[0].lessons[0].lessonId;
this.getFirstContent(this.firstTopic);
this.loadTopics = true;
});
},

Vue.js: how to have routing across 3 columns

I am trying to set up an page resembling:
========================================================================
+ Nav + Items + Individual Item +
+---------------+---------------+--------------------------------------+
+ * Cats + List + Individual Selected +
+ * Dogs + Of + Cat +
+ + Cats + OR +
+ + OR + Dog +
+ + Dogs + +
+ + + +
+ + + +
========================================================================
Usage example: Select 'Cats' in the 'Nav' column => retrieve a list of Cats (via REST/JSON) into the 'Items' column; Select an individual Cat from the list => retrieve an individual Cat (via REST/JSON) into the "Individual Item" column.
This looks like an application of Nested Routes (https://router.vuejs.org/guide/essentials/nested-routes.html) but my google-fu must be weak and I can't find a 3-level example like this anywhere.
It is easy to arrange an either/or approach where a single right-hand column renders either "List of Items" or 'Item.'
I have tried to use named views but I get to a point where I have 3 columns but when I render an 'Item' component, then the "List of Items" column is emptied.
It may be that I need to arrange to render both "List of Items" and 'Items' column at the same time (via 'components' in my router config) BUT these are remote REST calls so this is too heavyweight to be practical. Maybe 'computed' or 'watched' properties will assist in this case?
Is there an example of this three-level navigation somewhere?
Any help appreciated.
Edit:
this is the sort of thing I thought would be needed:
<div class="row">
<div class="col-2 bg-light sidebar">
<div class="sidebar-sticky">
<h3 class="h3 pl-3">Actions</h3>
<navigation />
</div>
</div>
<div class="col-3 ml-auto bg-info px-3">
<router-view />
</div>
<div class="col-7 bg-warning px-3">
<router-view name="entity" />
</div>
</div>
...
{
path: 'persons',
component: httpVueLoader('persons.vue'),
children: [
{
path: 'person/:id',
components: {
default: httpVueLoader('persons.vue'),
entity: httpVueLoader('person.vue')
}
}
]
},

My colorbox slideshow is not working properly

I want that when I click on view_attachments anchor then colorbox should be open, colorbox may have single or multiple images, if multiple then next and prev should be working.
[enter image description here][1]
<td>
<a class="view_attachments" expense_id="{{$expense->id}}" href="javascript:;">
<span class="glyphicon glyphicon-picture"></span>
</a>
{{--<span class="glyphicon glyphicon-picture"></span> --}}
<div>
#foreach($expense->attachments as $attachment)
<p>
<a class="group
<?php echo intval($expense->id);?>" href="{{asset("expense_attachments/voucher-" . $voucher_id ."/" . intval($expense->id) ."/" . $attachment->file_name . "")}}" title="">
</a>
</p>
#endforeach
</div>
</td>
<script>
$(function(){
$("a.view_attachments").on('click', function() {
var expense_id = $(this).attr("expense_id");
var $gallery = $(".group" + expense_id).colorbox({rel:'group' + expense_id,slideshow:true,width:'auto',innerWidth:'auto'});
$(".group" + expense_id).colorbox({rel:'group' + expense_id,slideshow:true,width:'auto',innerWidth:'auto'});
//e.preventDefault();
$gallery.eq(0).click();
});
});
// function view_attachments(expense_id)
// {
// //alert(expense_id);
// //$(".attachments" + expense_id).show();
// $.colorbox({rel:'group' + expense_id,width:'70%',innerWidth:'100%'});
// //$(".group" + expense_id).colorbox({rel:'group' + expense_id, slideshow:true});
// }
</script>
[1]: https://i.stack.imgur.com/Rf9eh.jpg

How can I add condition in class on vue.js 2?

My component vue is like this :
<template>
<a href="javascript:" class="btn btn-block" :class="{ product == 'responseFound' ? ' btn-default' : ' btn-success' }" #click="add($event)">
...
</template>
There exist error :
invalid expression: :class="{ product == 'responseFound' ? '
btn-default' : ' btn-success' }"
How can I solve it?
Simply remove the brackets in :class:
<template>
<a href="javascript:" class="btn btn-block" :class="product == 'responseFound' ? ' btn-default' : ' btn-success'" #click="add($event)">
...
</template>
If you want to add more conditions, wrap it with [] to create an array:
:class="[product == 'responseFound' ? ' btn-default' : ' btn-success', foo ? 'foo' : 'bar']"
I would use a computed property for this kind of behaviour.
Which removes the logic from your template, and moves it into your script part.
<template>
<a href="javascript:" class="btn btn-block" :class="classes" #click="add($event)">
</template>
<script>
export default {
computed: {
classes() {
return this.product == 'responseFound' ? 'btn-default' : 'btn-success'
}
}
}
</script>