How to get data by passing id into router from one vue component to another vue component through laravel axios - laravel

Employee.vue Component
<tr role="row" class="odd" v-for="(employee, index) in employees" :key="index">
<td>{{ index+1 }}</td>
<td><router-link :to="/employee-profile/+employee.id">{{ employee.name }}</router-link></td>
</tr>
I am sending employee id from here to EmployeeDetails.vue by routes in app.js
let routes = [
{ path: '/employee', component: require('./components/office/Employee.vue').default },
{ path: '/employee-details/:id', component: require('./components/office/EmployeeDetails').default },
]
Here is my EmployeeDetails.vue component
<script>
export default {
data() {
return {
employees:{},
}
},
mounted() {
let id = this.$route.params.id
axios.get('api/employee-details/'+id)
.then(response => {
this.employees = response.data;
});
}
}
</script>
Here is api.php file that I have called route through API resources
Route::get('employee-details/{id}', 'API\EmployeeController#employeeDetails');
and Here is my Controller EmployeeController.php where I have called function for return data
public function employeeDetails($id)
{
return DB::table('employees')->where('id', $id)->get();
}
But the problem is: Data is not showing and return a error message in my console. Error is given below. Actually I want How can I solve this error.
app.js:81221 [Vue warn]: Error in render: "TypeError: Cannot read property '0' of undefined"
found in
---> <EmployeeProfile> at resources/js/components/office/EmployeeProfile.vue
<Root>
app.js:82484 TypeError: Cannot read property '0' of undefined

It seems the id you are passing in the router link is incorrect.
It should be :
<router-link :to="`/employee-profile/${employee.id}`">{{ employee.name }}</router-link>

Related

Vue js with laravel not geting api data and response

this is Vue js component please help me to get data in template. getting data from vue js api in console i got undefined. Not getting blogList Data please help to get blog list data.
my api is correct and fetch data.
<template>
<div v-for="blog in blogList">
Hii i am {{ blog.name }} , {{ blog.mail }}
</div>
</template>
<script>
import ApiRequest from "../../js/api-request";
export default {
data() {
return {
blogList: '',
};
},
created() {
const request = new ApiRequest('/api/blog/list', (blogList) => {
this.blogList = blogList;
console.log(blogList);
}, () => {
//
});
request.get();
}
};
</script>

How to get data by axios call in a mounted component?

I'm working on getting data from API by performing api call with axios. But my attempts to get data from api aren't succesful. How to make it work?
export default {
mounted() {
this.fetchData()
},
data() {
return {
users:[]
}
},
methods: {
fetchData(){
axios.get('api/person')
.then(response => (this.users= response.data))
.catch(error => console.log(error));
}
},
}
In ExampleComponent have these lines
<template>
...
<div>{{users.name}}</div>
<div>{{users.ip}}</div>
...
</template>
In api.php
Route::get('/person', function() {
$users = DB::table('user_info')->select('ip','name')->get();
return $users;
});
Running php artisan tinker I did
DB::table('user_info')->select('ip','name')->get();
I've got all my data from DB(users with names and IP's).
In the dev console, I see my data in response tab. But it is nothing in my page.
you need v-for:
<div v-for="user in users">
<div>{{user.name}}</div>
<div>{{user.ip}}</div>
</div>
so for every users you will show info.
There is a problem in vue : it should be {users.ip} and {users.name} in template.
that is how i get my data.
<script>
export default {
data() {
return {
properties: []
}
},
methods: {
loadproperty(){
axios.get('allhouses').then(response => this.properties = response.data);
},
},
mounted() {
this.loadproperty();
}
}
</script>

Vue.js raise an error when view data in wrong case

I have the following template:
<template>
<div>
<h1>Users from SQL Server!</h1>
<p>This component demonstrates fetching data from the server.</p>
<table v-if="userlist.length" class="table">
<thead>
<tr>
<th>Id</th>
<th>First</th>
<th>Last</th>
<th>Date</th>
</tr>
</thead>
<tbody>
<!-- nb: These items must match the case they are passed in with (the Json passed back from .net Core serialises to lowerCamelCase) otherwise they will
show nothing and no error is raised! -->
<tr v-for="item in userlist">
<td>{{ item.userid }}</td>
<td>{{ item.firstname }}</td>
<td>{{ item.lastname }}</td>
<td>{{ item.createdonDate }}</td>
</tr>
</tbody>
</table>
<p v-else><em>Loading...</em></p>
</div>
This displays a table with no data. This is because the data passed in from the server has a different case to that used in the template items. If I fix them for example:
item.userId
item.firstName
item.lastName
item.createdOnDate
Then it works and data is displayed. The issue for me is that no error is returned. I am learning Vue using the .Net Core SPA template as a starter. But it took me a while to realise what I was doing wrong. If this was a model in the razor view it would have blown with a helpful error.
Is there a way to raise an error for this kind of thing?
I do have the Chrome Vue extension installed and realised the problem when I looked at the data there. But I was stumped for a while.
UPDATE 1: Thanks #ndpu for your solution but I am having trouble fitting it into my project. I have a boot.ts file like this:
import 'bootstrap';
import Vue from 'vue';
import VueRouter from 'vue-router';
Vue.use((VueRouter) as any);
Vue.config.devtools = true;
const routes = [
{ path: '/', component: require('./components/home/home.vue.html') },
{ path: '/counter', component:
require('./components/counter/counter.vue.html') },
{ path: '/fetchdata', component:
require('./components/fetchdata/fetchdata.vue.html') },
{ path: '/users', component: require('./components/users/users.vue.html') },
{ path: '/user', component: require('./components/user/user.vue.html') }
];
new Vue({
el: '#app-root',
router: new VueRouter({ mode: 'history', routes: routes }),
render: h => h(require('./components/app/app.vue.html'))
});
Where do I put the Object.prototype.safeGet? In there or in my component templates? Nowhere seems to work.
UPDATE 2:
I got it to work by putting the code from #ndpu into app.ts like this:
import Vue from "vue";
import { Component } from 'vue-property-decorator';
#Component({
components: {
MenuComponent: require('../navmenu/navmenu.vue.html')
}
})
export default class AppComponent extends Vue {
}
Object.defineProperty(Object.prototype, 'safeGet', {
get: function () {
return this;
}
});
Simplest way: define additional property to Object with getter that will only return himself.
/* eslint no-extend-native: ["error", { "exceptions": ["Object"] }] */
Object.defineProperty(Object.prototype, 'safeGet', {
get: function () {
return this;
}
});
So, by adding safeGet to any data attribute, you can be sure that you will get TypeError if attribute is undefined:
this:
<td>{{ item.userid.safeGet }}</td>
will produce exception (if actual property name is userId):
TypeError: Cannot read property 'safeGet' of undefined
FIDDLE: http://jsfiddle.net/yMv7y/2785/
Also, you can define simple method in object prototype to check property existence:
UPDATE: i couldn't make it work in 'complex' application with modules, webpack etc - vue trying to make added to Object.prototope method reactive. Didnt know why it is work in simple case like in applied fiddle.
Object.prototype.safeGet = function() {
var val, args = Array.prototype.slice.call(arguments);
var currLvlObj = this;
for (var i=0; i < args.length; i++) {
val = currLvlObj = currLvlObj? currLvlObj[args[i]] : undefined;
if (val === undefined) {
throw Error('property with name ' + args[i] + ' is undefined');
}
}
return val;
}
and use it like this:
<td>{{ item.safeGet('userid') }}</td>
this call should throw error (if actual property name is userId): Error: property with name userid is undefined
PS: nested objects properties can be accessed by passing all property names as arguments. For example, to access 'userId' in {'data': {'userId': 0}}:
<td>{{ item.safeGet('data', 'userid') }}</td>
FIDDLE: http://jsfiddle.net/yMv7y/2778/

Console error whilst waiting for API response - React/Redux

I am fetching data from a remote API in componentDidMount:
componentDidMount() {
this.props.fetchRemoteData('photos')
}
And then the received data is passed to my component props in mapStateToProps, using a selector to filter a specific object from the received array:
const mapStateToProps = (state, { params }) => {
const photoId = parseInt(params.photoId)
return {
singlePhoto: getSinglePhoto(state.filteredList.photos.jsonArray, photoId),
isFetching: state.filteredList.photos.isFetching
}
}
The content renders, but there is a split second before that, where it seems to be trying to the render the content before the data is successfully retrieved, which brings up the following error in the console:
Uncaught TypeError: Cannot read property 'charAt' of undefined
undefined is here referring to this.props.singlePhoto. But when singlePhoto receives the data payload the content renders.
Here is my container component:
class PhotoSingle extends Component {
componentDidMount() {
this.props.fetchRemoteData('photos')
}
render() {
const {singlePhoto, isFetching} = this.props
const photoTitle = capitalizeFirstLetter(singlePhoto.title)
return (
<div>
<PhotoSingleImg singlePhoto={singlePhoto} photoTitle={photoTitle} isFetching={isFetching}/>
</div>
)
}
}
const mapStateToProps = (state, { params }) => {
const photoId = parseInt(params.photoId)
return {
singlePhoto: getSinglePhoto(state.filteredList.photos.jsonArray, photoId),
isFetching: state.filteredList.photos.isFetching
}
}
import * as actions from '../actions/actionCreators'
PhotoSingle = connect(mapStateToProps, actions)(PhotoSingle)
export default PhotoSingle;
And my presentational component:
const PhotoSingleImg = ({ singlePhoto, photoTitle, isFetching }) => {
if (isFetching) {
return <h4>Fetching data...</h4>
}
return (
<div>
<h1>Single Photo</h1>
<h3>Title</h3>
<hr />
<img className='single-photo' src={singlePhoto.url} />
<p>Album ID: {singlePhoto.albumId} | Photo ID: {singlePhoto.id}</p>
</div>
)
}
export default PhotoSingleImg;
I'm unsure how to make it so the content will only attempt to render after I the API response has been received.
Any help appreciated.
Have you defined initial state in redux store?
You can try this way:
return singlePhoto ?
(<div>
<h1>Single Photo</h1>
<h3>Title</h3>
<hr />
<img className='single-photo' src={singlePhoto.url} />
<p>Album ID: {singlePhoto.albumId} | Photo ID: {singlePhoto.id}</p>
</div>) : null

Vue-Multiselect with Laravel 5.3

I'm new to Laravel and Vue and need help implementing Vue-Multiselect.
I don't know how to pass the actual options to the select.
My vue file:
<template>
<div class="dropdown">
<multiselect
:selected.sync="selected"
:show-labels="false"
:options="options"
:placeholder="placeholder"
:searchable="false"
:allow-empty="false"
:multiple="false"
key="name"
label="name"
></multiselect>
<label v-show="showLabel" for="multiselect"><span></span>Language</label>
</div>
</template>
<script>
import { Multiselect } from 'vue-multiselect';
export default {
components: { Multiselect },
props: {
options: {},
placeholder: {
default: 'Select one'
},
showLabel: {
type: Boolean,
default: true
},
selected: ''
}
};
</script>
My blade file:
<div class="form-group">
<drop-down
:options="{{ $members->list }}"
:selected.sync="selected"
:show-label="false"
></drop-down>
</div>
In my controller method I tried a few things:
1.
public function edit($id)
{
....
$members_list = Member::orderBy('member_first_name')->pluck('member_first_name', member_id');
return view('businesses.edit', compact('members_list'));
}
I got this error:
[Vue warn]: Invalid prop: type check failed for prop "options". Expected Array, got Object. (found in component: ).
2.I tried:
$members = Member::orderBy('member_first_name')->pluck('member_first_name', member_id');
$members_list = $members->all();
return view('businesses.edit', compact('members_list'));
I got this error:
htmlspecialchars() expects parameter 1 to be string, array given (View: C:\wamp\www\ccf.local\resources\views\businesses\edit.blade.php)
3.
$members = DB::table('members')
->orderBy('member_first_name', 'asc')
->get();
$members_list = array();
foreach($members as $mem) {
$members_list[$mem->member_id] = $mem->member_first_name;
}
I got this error: htmlspecialchars() expects parameter 1 to be string, array given (View: C:\wamp\www\ccf.local\resources\views\businesses\edit.blade.php)
So I need help with 2 things:
How to send the $members_list as the options
How can I combine the member_first_name and member_last_name fields so I can get options like this:
option value="member_id"
option text = member_first_name member_last_name
Thank you
When using prop binding inside of laravel {{ }} tries to output an escaped form of the variable.
what you need is a javascript array. if $members_list returns a collection, which seems to be indicated by your other code, try
<drop-down
:options="{{ $members_list->toJson() }}"
:selected.sync="selected"
:show-label="false"
></drop-down>
as for your controller this will help
$members = DB::table('members')
->orderBy('member_first_name', 'asc')
->get();
$members_list = $members->map(
function($member) {
return [
"value" => $member->member_id,
"label" => $member->member_first_name. " ". $member->member_last_name
];
}
);
Laravel Collections have a good selection of function that help to manipulate data will map your members array to the structure of { value: "", label: "" } when you convert to Json.
Lastly don't forget to set up your prop bindings in vue.
props: {
options: {
type: Array,
default: function() {
return [];
}
},...
}
That should get you going.

Resources