Null session on first useQuery after reloading page - session

I'm developping an application with a Next, TRPC and NextAuth (and Prisma but I believe there no issue with that one).
I have a page which displays a collection of elements. It retrieves the collection via an authenticated TRPC useQuery :
function Collection() {
const { data: session } = useSession();
const collectionsQuery = trpc.collectionRouter.collection.useQuery();
if (session) {
return (
<div>
<Layout>
<h1>Collections</h1>
<Link href="/collections/add" className="btn btn-sm btn-success mb-2">Add Collection</Link>
<div>
{
collectionsQuery.data && collectionsQuery.data.length != 0 ?
JSON.stringify(collectionsQuery.data)
:
<div className="p-2">No collections To Display</div>
}
</div>
</Layout>
</div>
);
} else {
return (
<div>Not logged</div>
)
}
}
It always fail when I reload the page, then when I navigate via my application menu to go to another page and come back to this page, all queries are successfull.
On server side (context,ts), the getSession returns null on reload page, then works on every further calls :
export async function createContext(opts: trpcNext.CreateNextContextOptions) {
const session = await getSession(opts);
if (session == null) {
console.log("null session");
}
return {
session,
};
};
What could cause the session to be null on page reload ?
Edit : When the query does not work on page reload, I see that the auth cookie is correctly set client side but is null on server side.
Edit 2 : This seems related to this one Don't get cookies in trpc context
But the advice of including the following piece of code in createTRPCNext / config does not work and does not even seem to get called :
headers: () => {
if (ctx?.req) {
// on ssr, forward client's headers to the server
return {
...ctx.req.headers,
'x-ssr': '1',
};
}

Related

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

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!");
}
},

Can't get wordpress ajax form to submit

I am porting an application to WordPress. It uses a form to select what attributes the customer is looking for in an Adult Family Home via checkboxes and drop-downs. It re-searches the database on each onchange and keyup. Originally I had the application standalone in PHP, but when I migrated it to WordPress I started having issues.
Currently in WP I have the code conditionalized ($DavesWay == 1) to do ajax the normal no-WordPress-way and ($DavesWay == 0) to do it the WordPress-way.
In the non-WordPress-way, the ajax works fine EXCEPT that I get a WP header and menu between the search form and the results-div that Ajax puts the data in. I get no errors from WP or in the JS console. In the WP-way The search form displayed, but nothing happens when I check any of the checkboxes. The JS console displays
POST http://localhost/demo4/wp-admin/admin-ajax.php 400 (Bad Request)
But I don't see any way to tell exactly what it is complaining about. How should I troubleshoot this?
Troubleshooting = Examine the HTML output, lots of echos and exits in PHP code, look at JS console.
function submitPg1(theForm) {
// Used with onChange from "most" form elements, but not on those that change the page
// rather than the select criteria. Such as rowsPerPage, pageNumber etc.
setById("pageNo", "1"); // set inital page
mySubmit();
}
function mySubmit(theForm) { // The actual ajax submit
// DO NOT set page number
jQuery.ajax({ // create an AJAX call...
data: jQuery("#asi_search_form").serialize(), // get the form data
type: jQuery("#asi_search_form").attr("method"), // GET or POST
url: jQuery("#asi_search_form").attr("action"), // the file to call
success: function (response) { // on success..
jQuery("#result").html(response); // update the DIV
}
})
}
function setById(id, value) { // Used to set vales by Id
x = document.getElementById(id).value;
x.value = value;
}
// 1st submit with blank selection
jQuery(document).ready(function () { submitPg1(this.form) });
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script>
Code fragments: (from the displayed page source)
<div id="asi_container" class="asi_container" >
<noscript><h2>This site requires Javascript and cookies to function. See the Help page for how to enable them.</h2></noscript>
<div id="searchForm">
<form id="asi_search_form" name="asi_search_form" method="post" action="http://localhost/demo4/wp-admin/admin-ajax.php">
<input type="hidden" name="action" value="asi_LTCfetchAll_ajax" style="display: none; visibility: hidden; opacity: 0;">
<table id="greenTable" class="asi_table" title="The Green areas are for site administration, not typical users">
<tbody>
PHP code:
$DavesWay = 0;
if ($DavesWay == 1){ //echo "Daves Way Setup"; // Dave's way, which works but prints the menu twice
if( $operation == "submit"){
require("asi_LTCfetchAll.php"); // for each onchange or onkeyup
}else{
add_filter( 'the_content', 'asi_tc_admin', '12' ); // Initial page refresh # must be >12
}
}else{
// The WordPress way that I could't get to work -- asi_LTCfetch never gets called
function asi_LTCfetchAll_ajax(){
//echo "<br /> Goto to Submit function"; // DEBUG
require($asi_plugin_dir . "/includes" . '/asi_LTCfetchAll.php');
}
add_action( "wp_ajax_asi_LTCfetchAll_ajax", "asi_LTCfetchAll_ajax" ); // admin users
add_action( "wp_ajax_nopriv_asi_LTCfetchAll_ajax", "asi_LTCfetchAll_ajax" ); // non-logged in users
add_filter( "the_content", "asi_tc_admin", "12" ); // Initial page refresh # must be >12
}
Try changing the JavaScript to the way WordPress recommends it in their documentation:
var data = {
'action': 'my_action',
'whatever': 1234
};
jQuery.post(ajaxurl, data, function(response) {
alert('Got this from the server: ' + response);
});
I suggest trying following URL: https://codex.wordpress.org/AJAX_in_Plugins
Also you can use the plugin: https://wordpress.org/plugins/ajax-search-lite/

Laravel - how to return json on current page instead of popup window

I'm building SPA with Laravel and Vuejs, so I want to let users signin with github on popup window but problem is that authorization callback function returns json data on popup window instead of current page.
Here is a code:
Client side
authenticate() {
window.open("login/github", "_blank", "toolbar=yes,scrollbars=yes,resizable=yes,top=500,left=500,width=400,height=400");
}
Server side
public function redirectToProvider($service, Request $request)
{
return Socialite::driver($service)->stateless()->redirect();
}
public function handleProviderCallback($service, Request $request)
{
$providerUser = Socialite::driver($service)->stateless()->user();
return new JsonResponse([
'data' => $providerUser
]);
}
I need to close popup window when user successfully sign in and than handleProviderCallback to return json on a current page. Any idea how can I solve this?
Parent window
<button type="button" onclick="openNewWindow()">Login With Github</button>
<script>
var win = null;
function openNewWindow() {
win = window.open("ukulele.html", "_blank", "toolbar=yes,scrollbars=yes,resizable=yes,top=500,left=500,width=400,height=400");
win.focus();
}
window.saveToken = function() {
console.log(win.document.getElementById('json_data_here').value)
}
</script>
Child window: After success login with github, save token to a hidden input and close window:
<input type="hidden" id="json_data_here" value="aadcs"/>
<script>
window.opener.saveToken();
window.close();
</script>

Saving the page state after choosing filters

I have some filters on a web page (checkboxes) and I modify the result list by ajax POST method. Is there a way that somehow I save the page state and send the URL link to someone so they open it in that state? Any help is appreciated.
By the way I'm using Laravel.
You can use parameters :
test.com/page?checkbox1=checked&checkbox2=checked
In your Laravel controller you can do this :
public function page($request) {
$checkboxes = array();
if ($request->has('checkbox1')) {
$checkboxes[] = true;
}
if ($request->has('checkbox2')) {
$checkboxes[] = true;
}
// ... and so on.
return view('page', compact('checkboxes'));
}
And set your php page like this :
<input type="checkbox" <?php checkboxes[$i++] ? 'checked' : '' ?> >
You can set the checkbox as parameter in the URL, and when the user go to your address, check if there is any of your params.
if so - set the checkboxes as you wish
just to get the general idea..
function getUrlParams(requested_param){
//check for params
return result;
}
if (getUrlParams(myCheckBox)){
$('#checkbox_on_page').prop( "checked", true );
}

AngularJS : ng-selectize is not initializing selctize options after AJAX call

I'm using ng-selectize directive to a select box using angularJS. Options to the slectbox are retrieved from an AJAX call. AJAX call response is coming in proper format.If do inspect element, select box options are populated properly. But in the UI, options are not rendered. Is there any specific reason for this behaviour? The same code is working fine in another place.
Here is my code:
HTML:
<select multiple="multiple"
ng-model="email.existing"
ng-options="obj.email for obj in emailLists track by obj.email"
placeholder="Choose from existing email address"
selectize>
Javascript
angular.module('myApp', [
'myApp.controllers',
'myApp.services',
'ngDialog',
'angular-selectize'
]);
angular.module('myApp.services', []).
factory('myAPIservice', function($http) {
var myAPI = {};
myAPI.getAllEmail = function( data ) {
return $http.post(APP_BASE_URL + "director/getallemail", data );
}
return myAPI;
});
angular.module('myApp.controllers', [])
.controller('myCntrl', function($scope, myAPIservice, ngDialog) {
myAPIservice.getAllDirectorsEmail({}).success(function (response) {
$scope.emailLists = response;
});
});
The above code retrieves email list from url. Sample response will look like this.
AJAX Response
If I change the javascript code to
angular.module('myApp.controllers', [])
.controller('myCntrl', function($scope, myAPIservice, ngDialog) {
$scope.emailLists = new Array({email:'abc#def.com'},{email:'lmn#opqr.com'})
});
and the response will be
Without AJAX call
Can anyone help me resolve this issue?

Resources