How to load data into a select input using vue js? - laravel

I have a file called PostJobCreate.vue where an Employer can create a new job post.
I also have a table called locations with address columns and location_name column.
An employer can have many locations.
I'm trying to load the employers Locations into a select field so that when they create a new Job Post, they know what Location it is for.
I'm loading all of the employers locations in locations: [].
so I could get a column like this this.locations.location_name.
How can I load all of the location_name into a select field, so that a User can select the location the Job Post is for?
This is what I have so far very basic:
<b-form-group label="Location Name" label-for="location_name">
<b-form-select
v-model="locations.location_name"
:options=""
id="location_name"
size="sm"
>
</b-form-select>
<div class="invalid-feedback" v-if="errors.location_name">{{ errors.location_name[0] }}</div>
</b-form-group>
I want to load the location_name field for every record in the table, inside the :options. I might need a v-for, but I'm not sure what to do next.
PostJobCreate.vue:
<template>
<div class="col-md-12 grid-margin stretch-card">
<div class="card">
<div class="card-body">
<h3 class="card-title">Post a Job</h3>
<form class="forms-sample" v-on:submit.prevent="createJobPosts">
<b-form-group
label="Employment Type"
label-for="employment-type"
>
<b-form-radio-group
id="employment-type"
v-model="jobPostsData.employment_type"
:options="jobPostsData.optionsTwo"
name="employment-type"
>
</b-form-radio-group>
<div class="invalid-feedback" v-if="errors.employment_type">{{ errors.employment_type[0] }}</div>
</b-form-group>
<b-form-group label="Job Title" label-for="job_title">
<b-form-select
v-model="jobPostsData.job_title"
:options="jobPostsData.optionsThree"
id="job_title"
placeholder="Enter job title"
>
</b-form-select>
<div class="invalid-feedback" v-if="errors.job_title">{{ errors.job_title[0] }}</div>
</b-form-group>
<b-form-group label="Job Description" label-for="job_description">
<b-form-textarea
v-model="jobPostsData.job_description"
id="job_description"
placeholder="Enter job description"
:rows="10"
:max-rows="12"
class="mb-2"
></b-form-textarea>
<div class="invalid-feedback" v-if="errors.job_description">{{ errors.job_description[0] }}</div>
</b-form-group>
<b-form-group label="Salary Range" label-for="salary">
<b-form-select
v-model="jobPostsData.salary"
:options="jobPostsData.options"
id="salary"
size="sm"
>
</b-form-select>
<div class="invalid-feedback" v-if="errors.salary">{{ errors.salary[0] }}</div>
</b-form-group>
<b-form-group label="Location Name" label-for="location_name">
<b-form-select
v-model="locations.location_name"
:options=""
id="location_name"
size="sm"
>
</b-form-select>
<div class="invalid-feedback" v-if="errors.location_name">{{ errors.location_name[0] }}</div>
</b-form-group>
<b-row>
<b-col class="text-left">
<b-button type="submit" variant="success" class="mr-2"
><i class="mdi mdi-check-circle"></i> Save</b-button
>
</b-col>
</b-row>
</form>
</div>
</div>
</div>
</template>
<script>
import * as employerService from '../../../services/employer_service.js';
import * as employerLocationService from '../../../services/employer_location_service.js';
export default {
name: "postJobCreate",
data() {
return {
locations: [],
jobPostsData: {
job_title: null,
optionsThree: [
{ value: null, text: 'Please select an option' },
{ value: 'Budtender/Retail', text: 'Budtender/Retail' },
{ value: 'Delivery/Courier', text: 'Delivery/Courier' },
{ value: 'Security', text: 'Security' },
{ value: 'Grower/Horticulturalist', text: 'Grower/Horticulturalist'},
{ value: 'Master Grower', text: 'Master Grower'},
{ value: 'Extraction', text: 'Extraction'},
{ value: 'Chemist', text: 'Chemist'},
{ value: 'Trimmer', text: 'Trimmer'},
{ value: 'Packagers', text: 'Packagers'},
{ value: 'Manufacturing', text: 'Manufacturing'},
{ value: 'Edible Production', text: 'Edible Production'},
{ value: 'Sales', text: 'Sales'},
{ value: 'Marketing', text: 'Marketing'},
{ value: 'Management', text: 'Management'},
{ value: 'Executive Level', text: 'Executive Level'},
{ value: 'Other', text: 'Other'},
],
job_description: '',
employment_type: 'Freelance',
optionsTwo: [
{ value: "Freelance", text: "Freelance", },
{ value: "Full Time", text: "Full Time", },
{ value: "Internship", text: "Internship", },
{ value: "Part Time", text: "Part Time", },
],
salary: '40,000 and under',
options: [
{ value: '40,000 and under', text: '40,000 and under' },
{ value: '40,000-50,000', text: '$40,000-50,000' },
{ value: '50,000-60,000', text: '$50,000-60,000' },
{ value: '60,000-70,000', text: '$60,000-70,000' },
{ value: '70,000-80,000', text: '$70,000-80,000' },
{ value: '80,000-90,000', text: '$80,000-90,000' },
{ value: '90,000-100,000', text: '$90,000-100,000' },
{ value: '100,000-150,000', text: '$100,000-150,000' },
{ value: '150,000-200,000', text: '$150,000-200,000' },
{ value: '200,000-250,000', text: '$200,000-250,000' },
{ value: '250,000-300,000', text: '$250,000-300,000' },
{ value: '300,000-350,000', text: '$300,000-350,000' },
{ value: '350,000-400,000', text: '$350,000-400,000' },
{ value: '400,000-450,000', text: '$400,000-450,000' },
{ value: '450,000-500,000', text: '$450,000-500,000' },
{ value: '500,000-1,000,000', text: '$500,000-1,000,000' },
{ value: '1,000,000+', text: '1,000,000+' }
],
},
errors: {}
};
},
mounted() {
this.loadLocations();
},
methods: {
createJobPosts: async function() {
let formData = new FormData();
formData.append('job_title', this.jobPostsData.job_title);
formData.append('job_description', this.jobPostsData.job_description);
formData.append('employment_type', this.jobPostsData.employment_type);
formData.append('salary', this.jobPostsData.salary);
formData.append('location_name', this.locations.location_name);
try {
const response = await employerService.createJobPosts(formData);
this.$router.push('/post-a-job');
this.$toast.success("Job Post created Successfully!");
} catch (error) {
switch (error.response.status) {
case 422:
this.errors = error.response.data.errors;
break;
default:
this.$toast.error("Some error occurred, please try again!");
break;
}
}
},
loadLocations: async function() {
try {
const response = await employerLocationService.loadLocations();
this.locations = response.data.locations.data;
} catch (error) {
this.$toast.error('Some error occurred, please refresh!');
}
}
}
};
</script>
<style scoped>
</style>
Thank you.

You could Change the option field names as follows :
<b-form-select
v-model="selectedLocation"
:options="locations"
id="location_name"
size="sm"
value-field="location_name"
text-field="location_name"
>
...
selectedLocation should be defined in data as follows :
data() {
return {
locations: [],
selectedLocation:null
. ..

Related

Implement vue draggable in a table. Laravel

I'm trying to create a survey with the option to order the questions that are displayed in a table when creating the survey.
I'm using vue draggable and the example works but I don't know how to use this with a table and still get the rows to be draggable
Example
<draggable v-model="section" #start="drag=true" #end="drag=false">
<div v-for="section in surveySections" :key="section.id">{{section.title}}</div
</draggable>
This is the table
<el-table
:data="form.question_id"
border>
<draggable v-model="surveyQuestions" #start="drag=true" #end="drag=false">
<el-table-column prop="title" label="Pregunta"></el-table-column>
<el-col :xs="5">
<el-table-column fixed="right" label="Operaciones">
<template slot-scope="scope">
<el-button
#click.native.prevent="deleteRow(scope.$index, form.question_id)"
type="text" size="small">
<span class="icon-create">Eliminar</span>
<i class="el-icon-delete-solid"></i>
</el-button>
</template>
</el-table-column>
</el-col>
</draggable>
</el-table>
How can I get this to work?
I must have 50 reputation to comment!
SO.
you can see elementUI Table组件实现拖拽效果
e.g
npm install sortablejs --save
// Element table must specify row-key . Otherwise, the order will be wrong
import Sortable from 'sortablejs'
<template>
<div style="width:800px">
<el-table :data="tableData"
border
row-key="id"
align="left">
<el-table-column v-for="(item, index) in col"
:key="`col_${index}`"
:prop="dropCol[index].prop"
:label="item.label">
</el-table-column>
</el-table>
<pre style="text-align: left">
{{dropCol}}
</pre>
<hr>
<pre style="text-align: left">
{{tableData}}
</pre>
</div>
</template>
<script>
import Sortable from 'sortablejs'
export default {
data() {
return {
col: [
{
label: '日期',
prop: 'date'
},
{
label: '姓名',
prop: 'name'
},
{
label: '地址',
prop: 'address'
}
],
dropCol: [
{
label: '日期',
prop: 'date'
},
{
label: '姓名',
prop: 'name'
},
{
label: '地址',
prop: 'address'
}
],
tableData: [
{
id: '1',
date: '2016-05-02',
name: '王小虎1',
address: '上海市普陀区金沙江路 100 弄'
},
{
id: '2',
date: '2016-05-04',
name: '王小虎2',
address: '上海市普陀区金沙江路 200 弄'
},
{
id: '3',
date: '2016-05-01',
name: '王小虎3',
address: '上海市普陀区金沙江路 300 弄'
},
{
id: '4',
date: '2016-05-03',
name: '王小虎4',
address: '上海市普陀区金沙江路 400 弄'
}
]
}
},
mounted() {
this.rowDrop()
this.columnDrop()
},
methods: {
//行拖拽
rowDrop() {
const tbody = document.querySelector('.el-table__body-wrapper tbody')
const _this = this
Sortable.create(tbody, {
onEnd({ newIndex, oldIndex }) {
const currRow = _this.tableData.splice(oldIndex, 1)[0]
_this.tableData.splice(newIndex, 0, currRow)
}
})
},
//列拖拽
columnDrop() {
const wrapperTr = document.querySelector('.el-table__header-wrapper tr')
this.sortable = Sortable.create(wrapperTr, {
animation: 180,
delay: 0,
onEnd: evt => {
const oldItem = this.dropCol[evt.oldIndex]
this.dropCol.splice(evt.oldIndex, 1)
this.dropCol.splice(evt.newIndex, 0, oldItem)
}
})
}
}
}
</script>
<style scoped>
</style>
element ui table Sortable.js

I don't know why this error comes inside Laravel?

I have made this code, I want to facilitate user to dynamically enter text and display fields which have values, but I'm unable to get the result when I run it laravel+VueJs component view. below is my code
<template>
<div>
<div>
<label>Name</label>
<input type="text" #change="addRow">
</div>
<div> <label>Email</label>
<input type="text" #change="addRow1">
</div>
<div v-for="row in rows" :key="row.id">
<button-counter :id="row.id" :value="row.value"></button-counter>
</div>
</div>
<script type="text/javascript">
Vue.component('button-counter', {
props: {
value: {
default: ''
}
},
template: '<input type="text" style="margin-top: 10px;" v-model="value" >',
})
export default {
mounted() {
console.log('Component mounted.')
},
data: {
rows: [],
count:0
},
methods: {
addRow: function () {
var txtCount=1;
id='txt_'+txtCount;
this.rows.push({ value:'MyName' , description: "textbox1", id });
},
addRow1: function () {
var txtCount=1;
id='txt2_'+txtCount;
this.rows.push({ value: "myEmail", description: "textbox2", id });
}
}
}
data should be a function that returns an object holding data you want to manipulate, and you need to define the id as a variable, here's a working Vue SFC
<template>
<div>
<div>
<label>Name</label>
<input type="text" #change="addRow" />
</div>
<div>
<label>Email</label>
<input type="text" #change="addRow1" />
</div>
<div v-for="row in rows" :key="row.id">
<button-counter :id="row.id" :value="row.value"></button-counter>
</div>
</div>
</template>
<script type="text/javascript">
Vue.component("button-counter", {
props: {
value: {
default: ""
}
},
template: '<input type="text" style="margin-top: 10px;" v-model="value" >'
});
export default {
data() {
return {
rows: [],
count: 0
};
},
methods: {
addRow: function() {
var txtCount = ++this.count;
let id = "txt_" + txtCount;
this.rows.push({ value: "MyName", description: "textbox1", id });
},
addRow1: function() {
var txtCount = ++this.count;
let id = "txt2_" + txtCount;
this.rows.push({ value: "myEmail", description: "textbox2", id });
}
}
};
</script>
Hope this helps

How to pass v-model into another v-model

this is my input, i want to put the value to password equals with ic_number without retyping again in password input. can we pass the ic_number to password v-model?
<div class="form-group">
<label>Ic Number</label>
<input
id="ic_number"
placeholder="Ic Number"
v-model="form.ic_number"
type="text"
name="ic_number"
class="form-control"
:class="{ 'is-invalid': form.errors.has('ic_number') }"
>
<has-error :form="form" field="ic_number"></has-error>
</div>
<div class="form-group">
<label>Password</label>
<input
id="password"
placeholder="Password"
v-model="form.password"
type="password"
name="password"
class="form-control"
:class="{ 'is-invalid': form.errors.has('passsword') }"
>
<has-error :form="form" field="password"></has-error>
</div>
current code in my vuejs application
export default {
data() {
return {
editMode: false,
users: {},
form: new Form({
id: "",
name: "",
ic_number:"",
no_phone:"",
email: "",
password: "",
type: "",
bio: "",
photo: ""
})
};
},
I want to pass like this but it shows nothing
password: password = this.ic_number,
you can use watch for ic_number, when ic_number change ,watch method will be use
export default {
data() {
return {
editMode: false,
users: {},
id: "",
name: "",
ic_number:"",
no_phone:"",
email: "",
password: "",
type: "",
bio: "",
photo: ""
};
},
watch:{
"ic_number":function(val,oldval){ this.password = val }
}
}
I am not sure do you means A to B and B to C
like this demo
app.vue
<template>
<div id="app">
<Test1 v-model="hello"></Test1>
<div>{{hello}}</div>
</div>
</template>
<script>
import Test1 from "./components/Test1";
export default {
name: "App",
data() {
return {
hello: "hello"
};
},
components: {
Test1
}
};
</script>
<style>
</style>
test1.vue
<template>
<div>
<input v-model="hello">
</div>
</template>
<script>
export default {
props: ["value"],
data() {
return {
hello: this.value
};
},
watch: {
hello: function(val, oldval) {
this.$emit("input", val);
}
}
};
</script>
<style>
</style>
if you'd just like to make the value of the password the same at the ic_number. You can just set that in the v-model directive, like so:
v-model="form.password = this.form.ic_number"

Vue 2 Imported Component Property or Method not defined

I'm attempting to nest some components - ultimately I would like to have a component which displays Posts, with a PostItem component used to render each post. Inside the PostItem, I want a list of related comments, with CommentItem to render each comment. I have the posts displayed using the PostItem with no errors, but as soon as I add the Comments I get errors. So to simplify, I've pulled the CommentsList component out and I'm just trying to display it on the page, manually loading in all comments - it's an exact copy of PostsList, except with comment replacing post, but it generates an error:
[Vue warn]: Property or method "commment" is not defined on the instance but referenced during render. Make sure that this property is reactive, either in the data option, or for class-based components, by initializing the property. See: https://v2.vuejs.org/v2/guide/reactivity.html#Declaring-Reactive-Properties.
found in
---> <Comment> at resources/assets/js/components/CommentItem.vue
<CommentsList> at resources/assets/js/components/CommentsList.vue
<Root>
CommentsList.vue
<template>
<div class="media-list media-list-divided bg-lighter">
<comment v-for="comment in comments"
:key="comment.id"
:comment="comment">
</comment>
</div>
</template>
<script>
import comment from './CommentItem'
export default {
components: { comment },
data: function() {
return {
comment: {
id: 1,
content: "",
edited: false,
created_at: new Date().toLocaleString(),
user: {
id: 1,
name: '',
}
},
comments: [
{
id: 1,
content: "",
edited: false,
created_at: new Date().toLocaleString(),
user: {
id: 1,
name: '',
}
}
]
};
},
created() {
this.fetchCommentsList();
},
methods: {
fetchCommentsList() {
axios.get('/api/comments').then((res) => {
//alert(JSON.stringify(res.data[0], null, 4));
this.comments = res.data;
});
},
createComment() {
axios.post('api/comments', {content: this.comment.content, user_id: Laravel.userId, vessel_id: Laravel.vesselId })
.then((res) => {
this.comment.content = '';
// this.comment.user_id = Laravel.userId;
// this.task.statuscolor = '#ff0000';
this.edit = false;
this.fetchCommentsList();
})
.catch((err) => console.error(err));
},
deleteComment(id) {
axios.delete('api/comments' + id)
.then((res) => {
this.fetchCommentsList()
})
.catch((err) => console.error(err));
},
}
}
</script>
CommentItem.vue
<template>
<div>
<a class="avatar" href="#">
<img class="avatar avatar-lg" v-bind:src="'/images/user' + comment.user.id + '-160x160.jpg'" alt="...">
</a>
<div class="media-body">
<p>
<strong>{{ commment.user.name }}</strong>
</p>
<p>{{ comment.content }}</p>
</div>
</div>
</template>
<script>
export default {
name: 'comment',
props: {
comment: {
required: true,
type: Object,
default: {
content: "",
id: 1,
user: {
name: "",
id: 1
}
}
}
},
data: function() {
return {
}
}
}
</script>
I'm pretty new to Vue - I've read so many tutorials and have been digging through the documentation and can't seem to figure out why its working for me with my PostsList component thats an exact copy. It also seems odd that I need both comment and comments in the data return - something that my working Posts version requires.
I'll drop in my working Posts components:
PostsList.vue
<template>
<div>
<div v-if='posts.length === 0' class="header">There are no posts yet!</div>
<post v-for="post in posts"
:key="post.id"
:post="post">
</post>
<form action="#" #submit.prevent="createPost()" class="publisher bt-1 border-fade bg-white">
<div class="input-group">
<input v-model="post.content" type="text" name="content" class="form-control publisher-input" autofocus>
<span class="input-group-btn">
<button type="submit" class="btn btn-primary">New Post</button>
</span>
</div>
<span class="publisher-btn file-group">
<i class="fa fa-camera file-browser"></i>
<input type="file">
</span>
</form>
</div>
</template>
<script>
// import CommentsManager from './CommentsManager.vue';
import post from './PostItem.vue';
export default {
components: {
post
},
data: function() {
return {
post: {
id: 1,
content: "",
edited: false,
created_at: new Date().toLocaleString(),
user: {
id: 1,
name: '',
}
},
posts: [
{
id: 1,
content: "",
edited: false,
created_at: new Date().toLocaleString(),
user: {
id: 1,
name: '',
}
}
]
};
},
created() {
this.fetchPostsList();
},
methods: {
fetchPostsList() {
axios.get('/api/posts').then((res) => {
//alert(JSON.stringify(res.data[0], null, 4));
this.posts = res.data;
});
},
createPost() {
axios.post('api/posts', {content: this.post.content, user_id: Laravel.userId, vessel_id: Laravel.vesselId })
.then((res) => {
this.post.content = '';
// this.post.user_id = Laravel.userId;
// this.task.statuscolor = '#ff0000';
this.edit = false;
this.fetchPostsList();
})
.catch((err) => console.error(err));
},
deletePost(id) {
axios.delete('api/posts' + id)
.then((res) => {
this.fetchPostsList()
})
.catch((err) => console.error(err));
},
}
}
</script>
PostItem.vue
<template>
<div class="box">
<div class="media bb-1 border-fade">
<img class="avatar avatar-lg" v-bind:src="'/images/user' + post.user.id + '-160x160.jpg'" alt="...">
<div class="media-body">
<p>
<strong>{{ post.user.name }}</strong>
<time class="float-right text-lighter" datetime="2017">24 min ago</time>
</p>
<p><small>Designer</small></p>
</div>
</div>
<div class="box-body bb-1 border-fade">
<p class="lead">{{ post.content }}</p>
<div class="gap-items-4 mt-10">
<a class="text-lighter hover-light" href="#">
<i class="fa fa-thumbs-up mr-1"></i> 0
</a>
<a class="text-lighter hover-light" href="#">
<i class="fa fa-comment mr-1"></i> 0
</a>
</div>
</div>
</div>
</template>
<script>
export default {
name: 'post',
props: {
post: {
required: true,
type: Object,
default: {
content: "",
id: 1,
user: {
name: "",
id: 1
}
}
}
},
data: function() {
return {
}
}
}
</script>

How to call the repaint() method?

Need a code example of repaint() method for dxList widget in Phonejs
NB: I want to call repaint() after a user action such as click.
Use the "repaint" method in the following manner:
<!--TRIGGER-->
<div data-bind="dxButton: { text: 'repaint dxList', clickAction: onClick }"></div>
<!--TARGET LIST-->
<div id="targetList" data-bind="dxList: { width: 100, dataSource: [{ key: 1, title: 'element_1'}, { key: 2, title: 'element_2' }, { key: 3, title: 'element_3' }] }">
<div data-bind="dxAction: '#itemDetailsViewName/{key}'" data-options="dxTemplate : { name: 'item' } ">
<div data-bind="text: title"></div>
</div>
</div>
onClick: function () {
var list = $("#targetList").dxList("instance");
list.option('width', 200);
list.repaint();
}

Resources