How to show data of a single id using Vue js? - laravel

I'm displaying all records on a page at this URI xxx.test/employer/search/filter-by. I'm using Algolia Search to display all of the records/results. I added a button called View Profile and attached an empty method to it called showProfile.
When a user clicks on this button, I want to display this specific profile/record on a new page by itself. If I was fetching data on my own, i.e. without Algolia's code I would be able to do this, but in this case I'm not really sure how to do this.
EmployerSearchComponent.vue:
<ais-instant-search
:search-client="searchClient"
index-name="candidate_profiles"
>
<ais-search-box v-model="query" class="mb-3" placeholder="Search by job title, company name or city..." />
<ais-configure
:restrictSearchableAttributes="['job_title', 'employment_type']"
:hitsPerPage="25"
/>
<b-row class="job-search-card">
<ais-hits class="w-100">
<template slot="item" slot-scope="{ item }">
<b-col cols="12" class="mb-3">
<b-card>
<div class="float-right">
<i class="flaticon-paper-plane"></i> View Profile
</div>
<h4 style="margin-bottom: 20px;"><router-link to="/">{{item.job_title}}</router-link></h4>
<p>Type: {{item.employment_type}}</p>
<b-card-text class="mt-2"><span v-if="item.experience && item.experience.length < 300">{{item.experience}}</span><span v-else>{{item.experience && item.experience.substring(0,300)+"..."}}</span></b-card-text>
</b-card>
</b-col>
</template>
</ais-hits>
<ais-pagination />
</b-row>
</ais-instant-search>
If I click on the network tab in the console, and on the algolia query search URI, I can see that the search results are in results[0].hits. Below is a screenshot of this data.
P.S. My data is empty it just contains algolia client ID's.
How can I display a single id on a new page? I understand that I need to get the id from the record that is being displayed, and show this information on a new page, but I don't know how to put it all together.
Again I think I'll need a route, so I created this
Route::get('/employer/search/filter-by/show/{id}', 'EmployerSearchController#show')->name('employer.search.show');
I'm using Laravel for my backend. Thanks in advance.
------------------------------------- UPDATED: -------------------------------------
I feel like I'm really close, but $itemId in my controller after I die and dump returns "undefined" for some reason.
router.js (Vue Router):
{
path: '/employer/search/filter-by/:itemId/show',
name: 'employer-search-index',
component: SearchIndex,
meta: {
breadcrumb: 'Search Candidates',
requiresAuthEmployer: true,
employerHasPaid: true
},
},
EmployerSearchComponent.vue - with the <router-link> button:
<template slot="item" slot-scope="{ item }">
<b-col cols="12" class="mb-3">
<b-card>
<div class="float-right">
<router-link class="apply-job-btn btn btn-radius theme-btn apply-it" :to="'/employer/search/filter-by/' + item.id + '/show'">View Profile</router-link>
</div>
<h4 style="margin-bottom: 20px;"><router-link to="/">{{item.job_title}}</router-link></h4>
<p>Type: {{item.employment_type}}</p>
<b-card-text class="mt-2"><span v-if="item.experience && item.experience.length < 300">{{item.experience}}</span><span v-else>{{item.experience && item.experience.substring(0,300)+"..."}}</span></b-card-text>
</b-card>
</b-col>
</template>
EmployerSearchController.php:
public function show ($itemId)
{
$candidateProfiles = CandidateProfile::with(['user', 'photo', 'resume', 'video'])
->where('id', '=', $itemId)->get();
return Response::json(array(
'candidateProfiles' => $candidateProfiles,
), 200);
}
api.php:
Route::get('/employer/search/filter-by/{itemId}/show', 'EmployerSearchController#show')->name('employer.search.show');
And Finally, in the .vue file that shows the Full Single Profile, I'm loading the data like this.
mounted() {
this.loadCandidateProfileData();
},
methods: {
loadCandidateProfileData: async function () {
try {
const response = await employerService.loadCandidateProfileData();
this.candidateProfiles = response.data.candidateProfiles;
} catch (error) {
this.$toast.error("Some error occurred, please refresh!");
}
},
}
And the employerService.js file from the above code:
export function loadCandidateProfileData(itemId, data) {
return http().get(`employer/search/filter-by/${itemId}/show`, data);
}

As you suggest, you'll need an API endpoint to fetch the data from, returning it as a JSON object. You'll need to add a route to your client-side routes that takes the job ID (or slug) as a parameter. In your job component, you can retrieve the route param (e.g. in the created() method) as $route.params.id, for example, and use that to fetch the data from your API.
If your Algolia search is returning all the data that you want to display on your single job listing page, you could just put that in your Vuex store and display it without having to make another HTTP request. The downside of that would be that if a user bookmarked the page to return to later, there'd be no data in the store to display.

Thank you to Nilson Jacques responses. If you follow our conversation.
Finally I got the itemId param from the route and passed it to loadCandidateProfileData() like this:
loadCandidateProfileData: async function() {
try {
const itemId = this.$route.params.itemId;
const response = await employerService.loadCandidateProfileData(itemId);
this.candidateProfiles = response.data.candidateProfiles;
console.log(this.candidateProfiles);
if (response.data.candidateProfiles.current_page < response.data.candidateProfiles.last_page) {
this.moreExists = true;
this.nextPage = response.data.candidateProfiles.current_page + 1;
} else {
this.moreExists = false;
}
} catch (error) {
this.$toast.error("Some error occurred, please refresh!");
}
},

Related

Getting response back from server but .html not sowing anything in wordpress ajax

On click I'm sending the id as data and then using query showing the name of user from WordPress database. I'm getting the response back from server but It is not adding when try to use .html(response).May be this is something to do with permission ?Like only admin can use the response?
If that's the case what I can do.
This is the ajax function:
function get_user_id() {
let get_current_user_id =jQuery(this).attr('id');
cur_user = '<?php echo get_current_user_id() ;?>';
var postdata_name = {action: "incoming_user_name_ajax_call",
param_user_to_chat: get_current_user_id,};
jQuery.post(ajaxurl, postdata_name, function (response) {
jQuery("#name-incoming-user").html(response);});
}
This is the function in functions.php
add_action("wp_ajax_incoming_user_name_ajax_call", "incoming_user_name_ajax_call_fn");
add_action("wp_ajax_nopriv_incoming_user_name_ajax_call", "incoming_user_name_ajax_call_fn");
function incoming_user_name_ajax_call_fn() {
global $wpdb;
$param_user_to_chat=isset($_REQUEST['param_user_to_chat'])?trim($_REQUEST['param_user_to_chat']):"";
if (!empty($param_user_to_chat)) {
$posts = $wpdb->get_results("SELECT distinct(display_name) FROM wp_users where
ID=$param_user_to_chat");
echo $posts[0]->display_name;
}
wp_die();}
Posting the HTML as well for everyone who want to know what jQuery(this).attr('id'); is doing. It is getting id "4" or "2" depending on click.
<div id="target">
<div class="user-list-hide" id="user-hide" style="display: block;">
<div id="4"><span>Jason Bradley</span>/div>
<div id="2"><span>John Saddington</span></div>
</div>
</div>
There was issue in your jquery code i.e : the way you were calling your get_user_id() function here you have use wrong selector to get your inner divs . So, to make it work change :
jQuery("#target").on("click", "div", get_user_id);
to
jQuery("#user-hide").on("click", "div", get_user_id);

svelte-sapper each block list item selection for deletion - get the id

I have a list of orders stored in a db. I use each block to display all orders with a delete button. When I click the delete button, I need to get the id of the CLICKED list item so I can look that order in the db and delete it. I don't know how to get the id of the CLICKED list item and pass it to handledelete function. How do I do that in svelte/sapper?
My code for the page that display all orders :
<script>
let orderz =[]
function handlesave() {
//save all the order data to db...
} // handlesave
function handleDelete () {
fetch('order', {
method: 'POST',
credentials : 'include',
headers: {
'Accept': 'application/json',
'Content-type' : 'application/json'
},
body: JSON.stringify({
// order id to send it to server to delete it from the db
})
}).then(response => response.json())
.then(responseJson => {
console.log("xxxxxxx:", responseJson.orderdetails )
})
.catch(error => console.log(error));
}
</script>
<form on:submit|preventDefault={handlesave}>
<button type="submit">Place Order</button>
</form>
<ul>
{#each orderz as order}
<li >
<p >{order.vendorid} - {order.vendorname} - {order.item}
- {order.price}</p>
<button on:click|once={handleDelete}>Delete</button>
</li>
{/each}
</ul>
You can tell the delete function which id was clicked by simply passing it in as an argument to the function:
function handleDelete(id) {
// Delete logic here
}
<button on:click="{() => handleDelete(id)}">Delete</button>
!! Note that you should not call handleDelete directly in your markup as this will execute the function immediately upon rendering (and thus effectively delete your entry as soon as it appears on screen)
Just add variable to your delete-function:
function handleDelete (id){
... use id to delete item in database...
}
Then add order id also to your on:click:
EDIT: on:click function call fixed as mentioned in other answer
<button on:click|once={()=>handleDelete(order.id)}>Delete</button>
There are other ways to do this, but this is the simplest one.
You don’t need once modifier, if you delete the item.
You will probably need a key with each-loop in order to keep list correctly updated after delete (key = thing.id in following example)
{#each things as thing (thing.id)}
<Thing current={thing.color}/>
{/each}
https://svelte.dev/tutorial/keyed-each-blocks

Vuejs and laravel -NaN value?

I want to recover a variable from controller and show it but its Show NaN instead of the value.
The idea is to claculate the the progress of my projects in function call progress in my controller and than show it in table in my Html code.
This is my function in controller and it return the correct value:
public function progress($id){
$tasks=Task::where(['projet_id'=>$id])->get();
$x=0;
$i=0;
foreach ($tasks as $task) {
$x = $x + $task->progress;
$i++ ;
}
$progress=$x/$i;
return $progress;
}
and this where i want to show the progress in project.vue:
<tr v-for="projet in projets.data" :key="projet.id" >
<td #change="avancemant(projet.id)">
{{ parseInt(100 * progress ) }}%
<img :src="`/img/icon/verif.png`" style="width:15px;
v-if="`${parseInt(100*progress)}`==100" >
</img>
<div class="progress">
<div class="progress-bar bg-success" role="progressbar" aria-valuenow="0"
id="progress" v-model="form.progress"
aria-valuemin="`${parseInt(100*task.progress)}`":style="
{'width':`${parseInt(100*progress)}%`}" aria-valuemax="100">
</div>
</div>
</td>
and this is my project.vue script:
export default {
data(){
return{
progress:'',
projets:{},
projet:{
id:''
},
}}
created(){
this.avancement(this.projet.id);
}
methods:{
avancemant($id){
axios.get('/api/progress/'+$id).then(({data})=>(this.progress =data.data));;
},
}
P.S : it show me in NaN%
In your created function, you tell vue to run the functioin this.avancement with a parameter of this.projet.id. Since you setup your data object to be the following:
data() {
return {
progress:'',
projets:{},
projet:{
id:''
},
}
}
This means that when your code executes the code inside the created hook, it will use the current state of your data.
created(){
this.avancement(this.projet.id); // this.projet.id's value at this point is '' (empty string)
}
So when your function then runs the http request, you are sending this:
axios.get('/api/progress/'+'').then(({data})=>(this.progress =data.data));
This probably breaks your API because it requires an id of some sorts.
At this point, I dont have enough info from your application or goal to know why you run this at created. But a solution to fix this as it is right now would be to add a condition inside your avancement function to not run it if the id is not valid.
methods:{
avancemant($id){
if(isNaN($id)) {
return
}
axios.get('/api/progress/'+$id).then(({data})=>(this.progress =data.data));;
},
}

Updating the DOM with change in an object (vue.js) - binding not working?

I have the app.js file where gmarkers is an array of objects :
var vm = new Vue({
el: '#lili',
data: {
listings: gmarkers
}
});
In my HTML file :
<div id="lili" >
<div
v-repeat="gmarker : listings"
class="listing listing-list col-sm-12"
style="height:50px;line-height:50px;"
data-cat="#{{gmarker.mycategory}}"
data-id="#{{gmarker.id}}"
>
<span style="color:black;">
<a target="_blank" href="#{{gmarker.listlink}}">
#{{ gmarker.listname }}
</a>
</span>
<span class="tag blue-back" style="margin-left:5px;">
<a target="_blank" href="#{{gmarker.catlink}}">
#{{gmarker.listcat}}
</a>
</span>
<span style="margin-left:20px;color:#bbb;">
#{{gmarker.distance}}km
</span>
</div>
</div>
When loading the page, the DOM loads correctly, displaying the list I'm looking for but when (after an ajax call in js) the gmarkers object changes, the DOM doesn't change.
The new gmarkers is totally created from scratch and containing new objects.
What am I missing ?
It sound like you are wrong about what data is being bound here. You are expecting data: {listings: gmarkers} to do binding between vm.listings and the gmarkers array. This isn't what it does. It copies the gmarkers data into the listings and doesn't listen to gmarkers anymore. See this fiddle for an example of what I think you are doing wrong.
We can fix the above fiddle by setting the vm.listings to the new array of objects after the ajax request.
vm.$set('listings', gmarkers);
You can see this in action in this updated fiddle.
It is actually pretty common to see a blank listings until ajax returns them. Here is some sample code that will call an ajax request when vue is ready and update the listings once it is finished. Note: this exampe uses vue-resources to perform the ajax request. You may not have this. You can always just use jQuery or javascript to perform this.
data: {
listings: []
},
ready: function () {
this.fetchListings();
},
methods: {
fetchListings: function () {
this.$http.get('/your/api/listings', function (response) {
this.$set('listings', response);
});
}
}
This fiddle shows the above code but pay attention to the differences required for the fake ajax request I used.

Login with ionic and material design

I have an ionic project with side menu and all.
Now I want to add in simple way and login cool form, like
http://ionicmaterial.com/
But the issue I didn't see any examples how to add it in exciting project that it will load the login form first and after that will redirect to regular page.
My project looks like:
app.config(function ($stateProvider, $urlRouterProvider) {
$stateProvider
.state('app', {
url: "/app",
abstract: true,
templateUrl: "templates/menu.html",
controller: 'AppCtrl'
})
.state('app.placeslists', {
url: "/placeslists",
views: {
'menuContent': {
templateUrl: "templates/placeslists.html",
controller: 'PlaceslistsCtrl'
}
}
})
How can I add the login page with authentication (token) that it will load first and how can I add the material for login page in easy way.
Thanks!!!
For implementing login, you would require these things
A Login State
A Login Template
Logic to handle your token
$stateProvider
.state('Login', {
url: "/Login",
templateUrl: "app/templates/Login.html"
})
<ion-view view-title="Login" align-title="left">
<ion-content style="background: url(img/login.jpg) center; background-size: cover;">
<div class="hero no-header flat">
<div class="content">
<div class="app-icon"></div>
<h1>Thronester</h1>
</div>
</div>
<div class="list">
<ion-md-input placeholder="Username" highlight-color="balanced" type="text" ng-model='user.username'></ion-md-input>
<ion-md-input placeholder="Password" highlight-color="energized" type="password" ng-model='user.password'></ion-md-input>
</div>
<div class="padding">
<button ui-sref="app.profile" class="button button-full button-assertive ink">Login</button>
</div>
<div class="button-bar social-login">
<button class="button button-small button-border icon-left ion-social-google button-assertive-900" ng-click='DoLogin(user)'>Login</button>
</div>
</ion-content>
</ion-view>
In your DoLogin function, you would need to handle hit your API for login, and receive your token. You would need to store this token. I use SQLlite plugin to store my token into a token table. There are different ways of storing token.
SQLite plugin
Local Storage
WebSQL
File ngCordova
and many more, I can provide you with code snippet using SQLlite.
var DB = window.sqlitePlugin.openDatabase({name: "Token.db", location: 1})
var CreateQuery = 'CREATE TABLE IF NOT EXISTS Token (id integer primary key, access_token TEXT)'
var InsertQuery = 'INSERT INTO Token (access_token) VALUES (?)'
var selectQuery = 'SELECT access_token FROM Token WHERE id = 1'
var Token = // the token you get from your server, make a $http resquest and get it
$cordovaSQLite.execute( DB,CreateQuery ).then(function () {
//table created
})
$cordovaSQLite.execute(DB, InsertQuery, [Token]).then(function(){
// token inserted into table
})
$cordovaSQLite.execute(DB, selectQuery).then(function (res) {
//getting token from table
$rootScope.TokenFromTable = res.rows.item(0).access_token;
})
Don't just copy paste from the code (it wont work), you would need build the logic on where to place all this code and in which order.
After you have received the authToken, you can set it as a common header for all you $http requests, and when user clicks on logout, just drop the table or drop the DB. ( go through the blogs in the link)
you can add new state login in app.js which will load login.html and controller and load it by defalut like:
.state('login', {
url: '/login',
templateUrl: 'templates/login.html',
controller: 'LoginCtrl'
})
// if none of the above states are matched, use this as the fallback
$urlRouterProvider.otherwise('/login');
and in login controller when you successfully login then you can redirect it to any page using $state.go('app.placeslists'); it will load regular pages.
I found at the end all info with demos
you can find also in:
https://github.com/zachsoft/Ionic-Material

Resources