Value rendered by Controller not getting displayed - symfony

So I'm working with Symfony 4.4 and I'm facing an issue here.
I have the following script responsible for getting the value of an input tag and sending it back as json to the controller
{% if summoner is defined %}
let res = {{ summoner.summonerLevel }}
{% endif %}
$("#valid-summoner").click(function () {
let data = {'sumoner_name':$("#riot-summoner-input").val()}
let url = `/coach/`
let xhr = new XMLHttpRequest
xhr.open("GET", url)
xhr.send(JSON.stringify(data))
console.log(data)
function loadXMLDoc()
{
document.getElementById("display-summonerLevel").innerHTML = `Summoner Level: <h2>${res}</h2>`
}
loadXMLDoc();
});
I have a controller method responsible for rendering the index page that's receiving this json and extracting the content and using it to render the page again but with another option which is that value.
...
$data = json_decode($request->getContent());
if(isset($data->sumoner_name) && !empty($data->sumoner_name)){
// We return the code
return $this->render('coach/index.html.twig', [
'coaches' => $coaches, 'summoner'=> $this->showSummoner($data->sumoner_name),
'current_user'=>$currentUser, 'combined'=>$call->fetchCoachRating($coaches)
]);
}else{
return $this->render('coach/index.html.twig', [
'coaches' => $coaches,
'current_user'=>$currentUser, 'combined'=>$call->fetchCoachRating($coaches)
]);
}
I don't know if this is actually the way you're supposed to do it. But it certainly isn't working..
console.log(data) in the script give back the following output
(index):445 {sumoner_name: 'YàKûZa'}sumoner_name: "YàKûZa"[[Prototype]]: Object
I'm not sure what I can do here

Related

Gutenberg Block Rendering from JSON

I am trying to make custom Gutenberg Blocks through a plugin. Everything is going smooth the only issue is when I select my block from the blocks menu, it just pastes the JSON on the front. What I rather want is to render this JSON to make blocks.
I am fetching blocks' content from an API. I am attaching my code as well.
function makeBlock(block, category){
var jsonBlock = {
"__file": "wp_export",
"version": 2,
"content": ""}
;
$.ajax({
type: "POST",
url: document.location.origin+"/blocknets/wp-admin/admin-ajax.php",
data: {
'action': 'makeBlocks',
'id': block.id
},
dataType: "json",
encode: true,
}).done(function (resp) {
// console.log(resp);
jsonBlock.content = resp.data.content;
});
( function ( blocks, element, data, blockEditor ) {
var el = element.createElement,
registerBlockType = blocks.registerBlockType,
useSelect = data.useSelect,
useBlockProps = blockEditor.useBlockProps;
// debugger;
registerBlockType( 'custom-blocks/'+category+'-'+block.id, {
apiVersion: 2,
title: block.name,
icon: 'megaphone',
category: category,
edit: ()=>{return jsonBlock.content},
save: () => null
} );
} )(
window.wp.blocks,
window.wp.element,
window.wp.data,
window.wp.blockEditor
);
}
Purple Highlighted is my plugin, and Yellow is what it prints out.
What I rather want is to render this JSON. If I just paste this JSON into code editor it would look like this.
Can anyone help me out?
The jsonBlock.content displayed in the Editor view is serialized block content. The first step is to use parse() to transform the content into valid blocks. Next, to render the blocks I found RawHTML can be used to render innerHTML from the block content. The <RawHTML/> component uses dangerouslySetInnerHTML as seen commonly in React to render inner HTML content. Eg:
Edit()
const { parse } = wp.blockSerializationDefaultParser;
const { RawHTML } = wp.element;
export default function Edit({ attributes, setAttributes }) {
// Example of serialized block content to mimic resp.data.content data
var content = "<!-- wp:paragraph --><p>paragraph one</p><!-- /wp:paragraph --><!-- wp:paragraph --><p>then two</p><!-- /wp:paragraph -->";
// Parse the serialized content into valid blocks using parse from #wordpress/block-serialization-default-parser
var blocks = parse(content);
// Iterate over each block to render innerHTML within RawHTML that sets up dangerouslySetInnerHTML for you..
return blocks.map((block, index) => <RawHTML key={index}>{block.innerHTML}</RawHTML>);
}
Nb. The example covers parsing and displaying block content in the Editor, it does not cover saving the content, as your existing save() function is set to null.
I was able to render all the blocks by using the following edit function:
edit: ()=>{
window.wp.data.dispatch( 'core/block-editor' ).insertBlocks( window.wp.blocks.parse( jsonBlock.content));
return null;
}

HTML entities are not being decoded when using WordPress REST API for Gutenberg blocks

I am building a custom Gutenberg block that makes a request to the WordPress REST API to get some Posts. I'm using axios to make the request to the REST endpoint.
When the result comes back, there is an array of Post objects, and I can see the titles of the Posts, but they are all contained in the JSON object as title.rendered and contain HTML entities eg.
title: {
rendered: "This has a hyphen – oh dear"
}`
I'm trying to populate a <SelectControl> with the resulting data, so there's no way to use the React dangerouslySetInnerHTML method which would solve the entities problem. So how can I get rid of these entities when populating the options?
Here is the code I'm using to populate the options from the REST response:
const options = response.data.map((post) => {
return {
label: post.title.rendered,
value: post.id,
};
});
It's not immediately obvious, but there is in fact a method made available in the Blocks API to do this.
At the top of your block code, type:
const { decodeEntities } = wp.htmlEntities;
Then you can use it like this:
const options = response.data.map((post) => {
return {
label: decodeEntities(post.title.rendered),
value: post.id,
};
});
Bazoozaa! HTML entities are gone.
And why not using rest_prepare_<post_type> filter ?
$post_type = "post";
add_filter( "rest_prepare_{$post_type}", 'prefix_title_entity_decode' );
function prefix_title_entity_decode( $response ) {
$data = $response->get_data();
$data['title']['rendered'] = html_entity_decode( $data['title']['rendered'] );
$response->set_data( $data );
return $response;
}

WP API and JS : Cannot read property 'wp:featuredmedia' of undefined

I write a component to display a list WP posts on a page build with nuxt.js and I just can not display the featured image.
The Vue Component
<template>
<div class="references__grid">
<div class="references__item" v-for="item in references">
<h3><nuxt-link :to="slugToUrl(item.slug)"><h2 class="is-title">{{ item.title }}</h2></nuxt-link></h3>
<div v-html="item.excerpt"></div>
<div>{{ item.image }}</div>
<strong class="more"><nuxt-link :to="slugToUrl(item.slug)">Lire la suite</nuxt-link></strong>
</div>
</div>
</template>
The request
getReferences() {
return new Promise((resolve, reject) => {
request.defaults.baseURL = this.baseUrl;
request.get(`posts?categories=46&per_page=6&_embedded`).then(response => {
const data = [...response.data];
if (response.status === 200 && response.data.length > 0) {
const filtered = {
total: response.headers["x-wp-total"],
totalPages: response.headers["x-wp-totalpages"],
data: data.map(item => ({
id: item.id,
title: item.title.rendered,
content: item.content.rendered,
excerpt: item.excerpt.rendered,
slug: item.slug,
image: item._embedded["wp:featuredmedia"][0].media_details.sizes.full.source_url
}))
};
resolve(filtered);
} else {
reject(response);
}
});
});
},
The WP Api seems ok: https://www.agencedebord.com/wp-json/wp/v2/posts?categories=46&per_page=61&_embed
The error message:
ERROR
TypeError: Cannot read property '0' of undefined
server-bundle.js:1525 filtered.data.data.map.item
server-bundle.js:1525:56
Array.map
server-bundle.js:1519 >__WEBPACK_IMPORTED_MODULE_1_axios___default.a.get.then .response
server-bundle.js:1519:24
next_tick.js:160 process._tickCallback
internal/process/next_tick.js:160:7
So why item._embedded is undefined?
There is no problem for item.id or item.slug... any clarification is appreciated.
Finally, I did not use "_embed" but I add a new endpoint following this answer : Get Image URL instead of Attachment Id in Rest API
I think that the request url is not correct, you should use _embed not _embedded
So it will be request.get(posts?categories=46&per_page=6&_embed)
Otherwise, the _embedded part will be missing in the json response.
The problem is sometimes item._embedded['wp:featuredmedia'] is returning undefined, you can confirm you get that by console.log(item._embedded['wp:featuredmedia']), the solution for that by wrapping it in if condition, if it not undefined to proceed if(item._embedded['wp:featuredmedia']){ return let imageUrl = item._embedded["wp:featuredmedia"][0].media_details.sizes.full.source_url
} else { return null}
I had one post that was giving this error. I had the if/else setup properly but it was still erroring. I went to the problem post and resaved the featured image and also changed to the ajax to load .full.source_url instead of .medium.source_url and that fixed the error.
I imported some photos from another wordpress. some of them had not featured images yet they somehow acting like they have. (has_post_thumbnail() was acting same way and returns true for that posts)
My solution is checking if they 'really' have thumbnail:
if(post.featured_media == 0 || post._embedded['wp:featuredmedia'][0].media_details == undefined){
imageSource = null;
}
else{
imageSource = post._embedded['wp:featuredmedia'][0].media_details.sizes.full.source_url;
}

How to setup an ajax call using symfony2

I have this simply ajax/jquery call to a symfony2 controller/action
$.ajax({
type: 'post',
url: 'http://symfony.local:8080/app_dev.php/api/searches/guitar.json',
success: function(results) {
}
});
I'd need to change the first part of the url 'http://symfony.local:8080/app_dev.php/api/searches/guitar.json' in order to make it independent from the front controller I'm using. How can I achieve this?
First, why are you supplying the whole URL? You could omit the domain part so that the path is relative:
$.ajax({
type: 'post',
url: '/app_dev.php/api/searches/guitar.json',
success: function(results) {
}
});
Second, you can set up the prefix for your AJAX calls in a Symfony view:
<script type="text/javascript"></script>
{% if app.environment == 'dev' %}
var root = '/app_dev.php/';
{% else %}
var root = '/';
{% endif %}
</script>
I've introduced a window.root variable here. You can use it in your scripts then:
// ...
url: root + '/api/searches/guitar.json',
// ...
And as suggested in the comments, the best way here would be passing the URL to your scripts with a separate routing provider for JavaScript.
You could set the url as the href and catch it or set it as some of data tag.
As href
Your link
Link
And the javascript
$('a.ajax-link', function (e) {
e.preventDefault();
// Stop link updating page
var href = $(this).attr('href);
$.ajax({
type: 'post',
url: href,
....
});
});
Or as a data field
Your link
<a data-href="{{ path('your_route') }}" class="ajax-link">Link</a>
And the javascript
$('a.ajax-link', function (e) {
e.preventDefault();
// Stop link updating page
var href = $(this).data('href);
... see above ...
});
With either of these ways there is no use for FOSJsRouting or hard coded routes.

Why isn't the URL being generated for this route?

So, I'm working on a Meteor project and I can't get this route to generate properly, or at all for that matter.
<template name="browseAll">
<h3>List of classes with books available!</h3>
<ul>
{{#each aggCount}}
<li>{{ _id }} ({{ count }})</li>
{{/each}}
</ul>
</template>
The data that is being iterated over is a result of aggregation using MongoInternals, and that is as follows:
(server/methods.js excerpt):
classCount: function() {
// Attempt aggregation of the books table to count by class, maybe.
var db = MongoInternals.defaultRemoteCollectionDriver().mongo.db;
var col = db.collection("books");
var aggregateSync = Meteor._wrapAsync(col.aggregate.bind(col));
var pipeline = [
{$group: {_id: "$class", count: {$sum: 1}}},
{$sort: {_id: 1}}
];
var theAnswer = aggregateSync(pipeline);
return theAnswer;
}
It seems that the data is coming through okay, and sample data from aggregation (coming into the template) looks like this:
[ { _id: 'ADNR1234', count: 2 }, { _id: 'ARTH1234', count: 1 } ]
That's the template code I've got, and this is the route that it's supposed to be working with:
this.route('browse-class', {
path: '/browse/:_class',
data: function() {
var booksCursor = Books.find({"class": this.params._class},{sort:{"createdAt": 1}});
return {
theClass: this.params._class,
numBooks: booksCursor.count(),
books: booksCursor
};
}
});
I don't understand it. The data is being SHOWN, and what I want to do is generate a URL for browse-class (route) that takes the value of {{ _id }} in the helper as a parameter, so as to generate something like this:
application.org/browse/CLSS
Be aware that {{pathFor}} must be called with a data context properly set :
{{#with class}}
{{pathFor "browse-class"}}
{{/with}}
Optionnaly it is possible to pass the data context as a parameter :
{{pathFor "browse-class" class}}
The data context provided to pathFor is used when generating the route path, if you defined a route path like this :
path: "/browse/:_id"
Then it will use the _id from the class to properly generate a URL.
For the text of the link, I doubt you want to display the _id, your class documents probably include a "label" so you could use this :
{{ label }}

Resources