$.post(url, data) doesn't work - json

I'm creating simple twitter_clone using Rails to create json API and ReactJS in frontend.
What I need now is to save new created tweet into DB and then to update an API in json which contain list of tweets to be able to use them to render a view.
To achieve it I try to use post request:
My add tweet function in main.jsx file
addTweet(tweetToAdd){
$.post("/tweets", { body: tweetToAdd }) //after saving to database
.success( savedTweet => {
let newTweetsList = this.state.tweetsList;
newTweetsList.unshift(savedTweet);
this.setState({tweetsList: newTweetsList});
})
.error(error => console.log(error));
}
There is a problem with delivering body of the tweet to database, cause after submitting there is NULL here.
Probably it means that body isn't send to DB ,but rest of parameters there are.
in /tweets there is an json API which looks like:
[{"id":17,"user_id":1,"body":null,"created_at":"2015-12-18T10:11:25.085Z","updated_at":"2015-12-18T10:11:25.085Z","name":"Marek Czyż"}]
When I create tweet manually form console everything works. so the problem must have been in previous piece of code.
Secondly after pressing SUBMIT tweet Ive recevied a warning that
Warning: Each child in an array or iterator should have a unique "key" prop. Check the render method of TweetList. See fb.me/react-warning-keys for more information.
although Ive got a key to every Tweet:
let tweets = this.props.tweets.map(tweet => );
Please, help me.

Assuming you're passing the right value as tweetToAdd, make sure you permit the body param in your controller. If it works in the console, it's not a validation problem, rather an unpermitted param.
As for the error you're seeing, you'll need to add a key prop to each rendered tweet. Something like:
render() {
let tweets = this.props.tweets;
return <ul>
{tweets.map(tweet => {
return <li key={tweet.id}>{tweet.body}</li>;
})}
</ul>;
}

Related

Parse a json object shows undefined

I was using OMDBapi to get the details of different movies. I successfully fetched the result and it returns a json object like this;
{"Title":"WWA: The Inception","Year":"2001","Rated":"N/A","Released":"26 Oct 2001","Runtime":"N/A","Genre":"Action, Sport","Director":"N/A","Writer":"Jeremy Borash","Actors":"Bret Hart, Jeff Jarrett, Brian James, David Heath","Plot":"N/A","Language":"English","Country":"Australia","Awards":"N/A","Poster":"https://m.media-amazon.com/images/M/MV5BNTEyNGJjMTMtZjZhZC00ODFkLWIyYzktN2JjMTcwMmY5MDJlXkEyXkFqcGdeQXVyNDkwMzY5NjQ#._V1_SX300.jpg","Ratings":[{"Source":"Internet Movie Database","Value":"6.0/10"}],"Metascore":"N/A","imdbRating":"6.0","imdbVotes":"22","imdbID":"tt0311992","Type":"movie","DVD":"N/A","BoxOffice":"N/A","Production":"N/A","Website":"N/A","Response":"True"}
Note that we get this type of object from the api if we want to get a particular movie details and that is what i was doing. Now to show the different details to a user, i started parsing this JSON object which works fine but when i try to get the value of the Value key present inside the Ratings key, it returns undefined.
I am working with react-native. After getting the data, i stored it inside the state, named it as details. Then to get it;
this.state.details.Title //if i wanted to get the Title and it works fine.
Then for Value inside Ratings;
this.state.details.Ratings[0].Value
But it returns undefined.
Also note that this works fine in pure Javascript as i parsed the dict in the browser console in the same way and it returned the correct value.
Here is more code;
componentDidMount() {
this.fetchData();
}
fetchData = async () => {
const response = await fetch(`http://www.omdbapi.com/?i=${this.props.navigation.getParam('i')}&apikey=******`) // where this.props.navigation.getParam('i') is the omdbid of the movie
const result = await response.json()
this.setState({details: result})
}
Here is error log;
undefined is not an object (evaluating 'this.state.details.Ratings[0]')
You're most likely trying to access state object before fetch has done it's job .... it's an async op ... so you should make sure your data is ready before rendering...
if (this.state.details) {
// start rendering...
}
More Explanation
your setState function should be executed right after fetch has finished its job, and since it's an async operation, it's going to take some time ...During that time, render function is executed with no state.details --> causing your issue ...
That's why you should check for state before rendering ... besides, the optional chaining trick Silversky Technology mentioned in his answer
If the value property you are accessing from the object might be not available for all the movies in the data you are getting from API response so it might cause you to error when accessing key from undefined objects.
To overcome the issue there is a way, you can try a fix as below:
this.state.details.Ratings[0]?.Value
The ? symbol lets the javascript not give an error when the value key not available in the object. it will make the accessing of property optional.
When storing objects in states it often causes problems as you are doing in line
this.setState({details: result})
Save result after strigifying it like
JSON.stringify(result)
this.setState({details: result})
Then when fetching form state, parse it back to object by
var result = JSON.parse(this.state.details)
Then you should be able to access it
You can access Ratings[0].Value by
this.state.details.Ratings && this.state.details.Ratings[0].Value
like,
<Text> {this.state.details.Ratings && this.state.details.Ratings[0].Value} </Text>

Getting [object][object] when trying to display data from api service

There are similar questions out there on StackOverflow but not exactly like mine.
When I check the Network tab in Inspector the data is being pulled from the api service. However, when I try to call it to the page I get [object][object].
Here's the structure of the data:
Object.widget.Value ... I would like to display the Value.
Here's how I am currently trying to call it:
{{i.widget}}
I've also tried json stringify and "| json" and those get me "undefined".
All other data that exists on the same level as widget is displaying fine and formatted the same. For some reason I can't pull widget's value.
Thanks for the help!
if this's what API return to us:
{name: "fox"}
in our component we can get it as:
data: any;
this.service.getData().subscribe((response) => {
this.data = response.body;
});
in our view if we put {{data}} it will return [object][object], you should set an property too in this case we have name which equal to fox, for example: {{data.name}};

How do I display json get result using Wix Code?

I'm working with a non-profit cat shelter trying to update their website. They want to have a page that connects to their shelter manager software to display the available cats for adoption. Luckily, their shelter manager offers API calls to get the information I need from it.
They use Wix as their platform and are pretty set on keeping it as most of their volunteers know how to make easy adjustments to other pages. I researched and found Wix offers the ability to connect to the API using their fetch method.
Basically, I am trying to get a dynamic page to display a repeater that is populated from their json API Get method.
Currently, for the backend I have (URL to API removed for security):
import {fetch} from 'wix-fetch';
export function getdata(){
return fetch('URL to API Service', {method: 'get'})
.then( (httpResponse) => {
if (httpResponse.ok) {
return httpResponse.json();
}
} );
}
On the page, this is where I think I am getting stuck:
import {getdata} from 'backend/fetchCats';
getdata()
.then(json => {
console.log(json);
var catData = json;
// static repeater data
$w.onReady(function () {
// handle creation of new repeated items
$w("#repeater1").onItemReady( ($item, itemData, index) => {
$item("#text23").text = itemData.ANIMALNAME;
} );
// set the repeater data, triggering the creation of new items
$w("#repeater1").data = catData;
} );
});
The above is giving me the error: Wix code SDK error: Each item in the items array must have a member named _id which contains a unique value identifying the item.
I know the JSON call has an ID field in it, but I am guessing Wix is expecting an _id field.
Am I just doing this wrong? Or am I missing something simple? I've spent a couple nights searching but can't really find a full example online that uses Wix's fetch method to get data via my HTTPS Get.
Thanks for any help!
You are doing fine.
You are getting the error from the line $w("#repeater1").data = catData;
which is the line used to set the items into the repeater. A repeater expects to have a _id member for each of the items, and your data quite probably does not have such an attribute.
I assume the API you are using, when returning an array, each item has some identifying attribute? if so, you can just do a simple transform like -
let catDataWithId = catData.map(item => {
item._id = item.<whatever id attribute>;
return item;
});
$w("#repeater1").data = catData;

Angular 4 html for loop displaying loosely typed object (string) normally but not when element is extracted directly?

I'm using Angular 4 to develop an app which is mainly about displaying data from DB and CRUD.
Long story short I found that in Angular 4 the component html doesn't like displaying loosely typed object (leaving the space blank while displaying other things like normal with no warning or error given in console) even if it can be easily displayed in console.log output, as shown in a string.
So I made a function in the service file to cast the values into a set structure indicating they're strings.
So now something like this works:
HTML
...
<div>{{something.value}}</div>
...
Component.ts
...
ngOnInit() {
this.route.params.subscribe(params => {
this.pkey = params['pkey'];
this.service.getSomethingById(this.pkey)
.then(
something => {
this.something = this.service.convertToStructure(something);
},
error => this.errorMessage = <any>error);
});
}
...
Code of the function convertToStructure(something)
convertToStructure(someArr: myStructure): myStructure {
let something: myStructure = new myStructure();
something.value = someArr[0].value;
return something;
}
But as I dig into other files for copy and paste and learn skills from what my partner worked (we're both new to Angular) I found that he did NOT cast the said values into a fixed structure.
He thought my problem on not being able to display the values (before I solved the problem) was because of me not realizing it was not a plain JSON object {...} but an array with a single element containing the object [{...}] .
He only solved half of my problem, cause adding [0] in html/component.ts was not able to make it work.
Component.ts when it did NOT work
...
ngOnInit() {
this.route.params.subscribe(params => {
this.pkey = params['pkey'];
this.service.getSomethingById(this.pkey)
.then(
something => {
console.log(something[0].value); //"the value"
this.something = something[0]; //html can't find its value
},
error => this.errorMessage = <any>error);
});
}
...
HTML when it did NOT work
...
<div>{{something[0].value}}</div> <!--Gives error on the debug console saying can't find 'value' of undefined-->
...
And of course when I'm using the failed HTML I only used this.something = something instead of putting in the [0], and vice versa.
So I looked into his code in some other page that display similar data, and I found that he used *ngFor in html to extract the data and what surprised me is that his html WORKED even if both of our original data from the promise is identical (using the same service to get the same object from sever).
Here's what he did in html:
...
<div *ngFor="let obj of objArr" ... >
{{obj.value}}
</div>
...
His html worked.
I'm not sure what happened, both of us are using a raw response from the same service promise but using for loop in html makes it automatically treat the value as strings while me trying to simply inject the value fails even if console.log shows a double quoted string.
What's the difference between having the for loop and not having any for loop but injecting the variable into html directly?
Why didn't he have to tell Angular to use the set structure indicating the values are strings while me having to do all the trouble to let html knows it's but a string?
The difference here is as you said that your JSON is not simple object , its JSON Array and to display data from JSON array you need loop. So, that is why your friends code worked and yours did not. And please also add JSON as well.

Send both JSON response and model in Grails

I'm new to Grails and I'm stuck up with a problem. I want to know if there is a way to send both JSON and view and model through "render" in Grails.
I'm using a jQuery Datatable to display data returned from server which is read from JSON returned by the controller. I also need to display error messages on the same view in case of validation failure in form fields. But I'm able to return either only the JSON or model and view using render. I also tried sending the JSON through model itself but it didn't work.
This is my code:-
def hierarchyBreakInstance = new HierarchyBreak(params);
String json = "{\"sEcho\":\"1\",\"iTotalRecords\":0,\"iTotalDisplayRecords\":0,\"aaData\":[]}";
hierarchyBreakInstance.errors.reject(message(code: 'hierarchyBreak.error.division.blank'));
render(view: "hierarchyBreak", model: [hierarchyBreakInstance: hierarchyBreakInstance]);
//render json;
The gsp code:-
<g:hasErrors bean="${hierarchyBreakInstance}">
<div class="errorMessage" role="alert">
<g:eachError bean="${hierarchyBreakInstance}" var="error">
<g:if test="${error in org.springframework.validation.FieldError}" > data-field-id="${error.field}"</g:if>
<g:message error="${error}"/>
</g:eachError>
</div>
</g:hasErrors>
Could you please let me know if there is a way to do this. Thanks!
You can use like this.
def hierarchyBreakInstance = new HierarchyBreak(params);
String json = "{\"sEcho\":\"1\",\"iTotalRecords\":0,\"iTotalDisplayRecords\":0,\"aaData\":[]}";
hierarchyBreakInstance.errors.reject(message(code: 'hierarchyBreak.error.division.blank'));
render(view: "hierarchyBreak", model: [hierarchyBreakInstance: hierarchyBreakInstance,json:json]);
//render json;
Assuming that you are doing a request with some parameters, and need to return if was succesfull or not, and the data to fill the table with ajax.
I will do on that way, use the statuses of the HTTP to mark if it was a problem with the validation(normally we return 400 Bad Request and the message)
Example :
return ErrorSender.sendBadRequest("error validating field $field with value $value")
And the errorsender has a sendBadRequest method
[response: ['message': message, error: "bad_request", status: 400, cause: []], status: 400]
If the request was OK, you only need to respond the data with something like
return [response: results, status: 200]
In the client side you have to have one function if the request was OK to parse result, and one function if request have some validated data problem, database problem or whatever that caused that the request didn´t return a 200(in the example),there are more status codes, you can check on
http://en.wikipedia.org/wiki/List_of_HTTP_status_codes
PD: Initial validation should be done on client side.