I'm using Api-Platform and React as client.
I have a Forum entity which contains other objects : an author (User entity) and a category (Category entity).
I embedded these entities with #Groups annotations to retrieve them more easily.
For instance, when I fetch /api/forums/ on Postman I get this result :
{
"#context": "/api/contexts/Forum",
"#id": "/api/forums",
"#type": "hydra:Collection",
"hydra:member": [
{
"#id": "/api/forums/79",
"#type": "Forum",
"id": 79,
"subject": "Sujet numéro 0",
"message": "Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.",
"category": {
"#id": "/api/categories/183",
"#type": "Category",
"title": "Category 2"
},
It seems good : we can see my category object is linked to Forum in hydra:member array, and a "title" field.
But I noticed that the result I really get is different in my react app for all my nested objects.
I only get the IRIs..
For instance with the same request :
...
fetch('forums')
.then(response =>
response
.json()
.then(retrieved => ({ retrieved, hubURL: extractHubURL(response) }))
)
.then(({ retrieved, hubURL }) => {
retrieved = normalize(retrieved);
...
I get this result :
{
"#context": "/api/contexts/Forum",
"#id": "/api/forums",
"#type": "hydra:Collection",
"hydra:member": [
{
"#id": "/api/forums/79",
"#type": "Forum",
"id": 79,
"subject": "Sujet numéro 0",
"message": "Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.",
"category": "/api/categories/183",
Every other fields have disapeared on "category", and I don't get why.
Could anyone help me with that ?
Thanks in advance
I found the solution (how silly of me), so I share you the tip :
In src/utils/dataAccess file, there is a normalize function :
export function normalize(data) {
if (has(data, 'hydra:member')) {
// Normalize items in collections
data['hydra:member'] = data['hydra:member'].map(item => normalize(item));
return data;
}
// Flatten nested documents
return mapValues(data, value =>
Array.isArray(value)
? value.map(v => get(v, '#id', v))
: get(value, '#id', value)
);
}
It appears that this function is called after each fetch :
return fetch(id)
.then(response =>
response
.json()
.then(retrieved => ({ retrieved, hubURL: extractHubURL(response) }))
)
.then(({ retrieved, hubURL }) => {
//retrieved = normalize(retrieved);
dispatch(loading(false));
dispatch(success(retrieved));
....
As you can see, I just commented the normalize line (useless in my case). Do that wherever it is needed, and everything should work again !
Related
I am attempting to create an angularjs bootstrap accordion that scrolls the accordion to the top when opened.
These solutions are close to what I would like to do:
AngularJS / ui-bootstrap accordion - scroll to top of active (open) accordion on click
https://www.peterbouda.eu/making-an-angular-ui-bootstrap-accordion-scrolling-to-top-when-opening.html
However, they use a timeout or scope watches. I would like to avoid using these unless absolutely necessary.
Is there a way to accomplish this without using $watch or setTimeout?
Here is a plunk of what i am trying to do, this is using the $watch: https://plnkr.co/edit/XQpUdrdjqaCGom4L9yIJ
app.directive( 'scrollTop', scrollTop );
function scrollTop() {
return {
restrict: 'A',
link: link
};
}
function link( scope, element ) {
scope.collapsing = false;
var jqElement = $( element) ;
scope.$watch( function() {
return jqElement.find( '.panel-collapse' ).hasClass( 'collapsing' );
}, function( status ) {
if ( scope.collapsing && !status ) {
if ( jqElement.hasClass( 'panel-open' ) ) {
$( 'html,body' ).animate({
scrollTop: jqElement.offset().top - 30
}, 500 );
}
}
scope.collapsing = status;
} );
}
The directive can be simplified to:1
app.directive( 'scrollTop', function scrollTop($timeout) {
return {
restrict: 'A',
link: postLink
};
function postLink(scope, elem, attrs) {
elem.on("click", function(e) {
if (scope.status.isOpen) {
$timeout(function() {
$( 'html,body' ).animate({
scrollTop: elem.offset().top - 30
}, 500 );
});
}
});
}
})
<uib-accordion>
<div heading="Section Title" is-open="status.isOpen"
ng-repeat="section in vm.sections"
scroll-top
uib-accordion-group>
<uib-accordion-heading>
<div ng-class="{isOpen: vm.isOpen}">
<h3>{{section.sectionTitle}}</h3>
<p>{{section.sectionSubHeader}}</p>
</div>
</uib-accordion-heading>
<div class="clearfix">
<b>Index+1={{$index+1}}</b>
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor
in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
</div>
</div>
</uib-accordion>
The $timeout is necessary because the browser needs to render the DOM with the newly opened and closed elements before it can compute the proper scroll offset.
The DEMO on PLNKR
I have found a way to do this from the controller.
I added a function that is triggered on ng-click to report the is-open status of the accordion.
Using the component lifecycle hook $doCheck I was able to watch for changes to the state of vm.isOpen. $doCheck runs on the end of every digest cycle, so I did not need to set a $scope.watch or $timeOut
The $doCheck runs essentially the same code as the directive in the question
app.controller('homeController', function($state, $element, sections, $transitions) {
var vm = this;
vm.$onInit = function() {
vm.sections = sections.getSections();
};
function updateOpenStatus() {
vm.collapsing = false;
vm.isOpen = vm.sections.some(function(item) {
return item.isOpen;
});
}
vm.$doCheck = function() {
if (vm.isOpen) {
var elem = $element.find('.panel-collapse');
var status = elem.hasClass('collapsing');
if (vm.collapsing && !status) {
var parentElem = elem.closest('.panel-open');
if (elem.parent().hasClass('panel-open')) {
$('html,body')
.stop()
.animate({
scrollTop: parentElem.offset().top - 52
}, 'fast');
}
}
vm.collapsing = status;
}
};
});
I updated the uib-accordion to call the function in the controller
<uib-accordion>
<div heading="Section Title" is-open="section.isOpen" ng-repeat="section in vm.sections" scroll-top uib-accordion-group>
<uib-accordion-heading>
<div ng-class="{isOpen: section.isOpen}" ng-click="vm.toggleOpen()">
<h3>{{section.sectionTitle}}</h3>
</div>
</uib-accordion-heading>
<div class="clearfix">
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor
in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
</div>
</div>
</uib-accordion>
Updated Plnkr: https://plnkr.co/edit/5EqDfmVOa0hzFfaQqdI0?p=preview
I have a react component , and I want to fill its state by fetching data from the url that I tested in browser and returns json data . but in my code I got nothing, here is my code :
fetch(`https://s3-us-west-2.amazonaws.com/s.cdpn.io/3/posts.json`)
.then(response => response.json())
//.then(data => JSON.stringify(data))
.then(data => this.setState({
latitude: position.coords.latitude, // this ois ok
longitude: position.coords.longitude, /// this is ok
locations : data // here I get {}
}));
Problem is here in my render function
const { location } = this.state.locations;
alert("1" +JSON.stringify( this.state.locations));
alert("2" + JSON.stringify( location));
First alert is full with correct data but second alert returns undefined.
It looks like you're trying to destructure location from this reponse:
{
"posts": [
{
"_id": "5b3f761e21d434001487ad99",
"title": "Hello Word!",
"content": "The world is green!",
"__v": 0
},
{
"_id": "5b3f76b521d434001487ad9a",
"title": "Sed porttitor lectus nibh",
"content": "Sed porttitor lectus nibh. Praesent sapien massa, convallis a pellentesque nec, egestas non nisi. Pellentesque in ipsum id orci porta dapibus. Proin eget tortor risus. Pellentesque in ipsum id orci porta dapibus. Curabitur aliquet quam id dui posuere blandit. Quisque velit nisi, pretium ut lacinia in, elementum id enim. Pellentesque in ipsum id orci porta dapibus. Vestibulum ac diam sit amet quam vehicula elementum sed sit amet dui. Vestibulum ac diam sit amet quam vehicula elementum sed sit amet dui.",
"__v": 0
}
]
}
As you can see, it doesn't have a location property so the result of your destructure will be undefined. Are you hitting the right endpoint?
I have a postgres table which stores some JSON using Groovy sql, I want to append an object to my 'players' array to add a new player to my database. At the moment I am trying this.I try to target my 'players' array and append my new json which comes from the server. This gives me an error
.PSQLException: ERROR: function array_append(jsonb, jsonb) does not
exist
I think I may be getting this error has the first param needs to be an array not jsonb, is there a way to target the array in my db so it comes back as an array? Or is there a better way to append this object to my array?
sql.executeUpdate("""
UPDATE site_content
SET content = array_append(content->'playersContainer'->'players', '${json}'::jsonb);
where id = :id
""", id: player.teamId)
}
Here is my JSON
"playersContainer": {
"players": [
{
"id": "1",
"name": "Nick Pocock",
"teamName": "Shire Soldiers",
"bio" : "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nulla imperdiet lorem tellus, in bibendum sem dignissim sed. Etiam eu elit sit amet lacus accumsan blandit sed ut dolor. Mauris vel dui non nisi vestibulum commodo vel id magna. Donec egestas magna in tincidunt mollis. Fusce mauris arcu, rhoncus ut lacus sed, fermentum ultrices elit. In sollicitudin at ex dapibus vestibulum. Pellentesque congue, est id lobortis viverra, mauris lectus pharetra orci, ut suscipit nisl purus vehicula est. Aliquam suscipit non velit vel feugiat. Quisque nec dictum augue.",
"ratings": [
1,
5,
6,
9
],
"assists": 17,
"manOfTheMatches": 20,
"cleanSheets": 1,
"data": [
3,
2,
3,
5,
6
],
"totalGoals": 19
}
}
My column is called content which holds the JSONb
For 9.5:
UPDATE site_content
SET content = jsonb_set(content, '{playersContainer,players}'::text[], content->'playersContainer'->'players' || '${json}'::jsonb);
where id = :id
I'm trying to use this Perl Method: HTML::Highlight - A module to highlight words or patterns in HTML documents.
The methode itself isn't acctualy the problem but the way how I can pass a Attribute.
Example which works:
use HTML::Highlight;
$text = 'Lorem ipsum Velit ullamco ex anim quis Duis laboris ut proident velit eu dolor Ut amet proident aliqua minim officia sunt commodo veniam dolor id reprehenderit reprehenderit non nulla incididunt mollit exercitation minim commodo ut quis laboris ex proident.';
# create the highlighter object
my $hl = new HTML::Highlight (
words => [
'ex',
'ul',
],
wildcards => [
undef,
],
colors => [
'red; font: bold',
],
debug => 0
);
my $hl_document = $hl->highlight($text);
print $hl_document;
What I'd like to do is something like this:
use HTML::Highlight;
$text = 'Lorem ipsum Velit ullamco ex anim quis Duis laboris ut proident velit eu dolor Ut amet proident aliqua minim officia sunt commodo veniam dolor id reprehenderit reprehenderit non nulla incididunt mollit exercitation minim commodo ut quis laboris ex proident.';
# create the highlighter object
#keywords = "ex", "ul";
my $hl = new HTML::Highlight (
words => #keywords,
wildcards => [
undef,
],
colors => [
'red; font: bold',
],
debug => 0
);
my $hl_document = $hl->highlight($text);
print $hl_document;
As you can see in the code snippet above, I'd like to pass an existing array to the object.
How can I do that correctly?
Currently I get an exeption like that:
HTML::Highlight - "words" and "wildcards" parameters must be references to arrays at C:\Skripts\Perl\syntax_highlight.pl line 8.
As said in error message, pass a reference:
my $hl = HTML::Highlight->new(
words => \#keywords,
# here __^
wildcards => [
undef,
],
colors => [
'red; font: bold',
],
debug => 0
);
I'm new to Backbone and struggling with what appears to be a basic problem. I have a route set up to take in a parameter, use it to locate a model (hard-coded at this point), and render the model data in a view.
Working with a parameter of "project1", in the render function of my view I can access this.model and project1.attributes and project1.get('name') but I cannot access this.model.attributes or this.model.get('name') or use this.model.toJSON(). (Note: trying to access any of those latter ones causes the app to bomb.)
Is this a "this" bind problem? Any help is appreciated.
var Router = Backbone.Router.extend({
routes: {
"work/:project" : "project"
},
project: function (project) {
$('#content').html(new ProjectView({model:project}).render().el);
}
});
var ProjectView = Backbone.View.extend({
id: "project",
render: function () {
$(this.el).html(this.template(this.model.toJSON()));
return this;
}
});
var Project = Backbone.Model.extend({});
var project1 = new Project({
name: "Project1",
description : "Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat."
});
As the comments have already mentioned, your basic problem is that you're passing a string to a View, but that View is expecting a Model. This line:
$('#content').html(new ProjectView({model:project}).render().el);
Is the problem: project needs to be an instance of Backbone.Model, but it's not. That line should instead look something like this:
var project1 = new Project({
name: "Project1",
description : "Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat."
});
$('#content').html(new ProjectView({model: project1}).render().el);