I have a problem with my application. Anyone can help me?
Error:
Converting circular structure to JSON
My Service to create items and save on localstorage:
addItem(item: Item): void {
this.itens.unshift(item);
let itens;
if (localStorage.getItem('itens') == null){
itens = [];
itens.unshift(itens);
localStorage.setItem('itens', JSON.stringify(itens));
} else {
JSON.parse(localStorage.getItem('itens'));
itens.unshift(itens);
localStorage.setItem('itens', JSON.stringify(itens));
}
}
And my component.ts:
addItem(): void {
this.itemAdicionado.emit({
nome: this.nome,
unidade: this.unidade,
quantidade: this.quantidade,
preco: this.preco,
perecivel: true,
validade: this.validade,
fabricacao: this.fabricacao,
});
this.nome = '';
this.unidade ;
this.quantidade ;
this.preco;
this.validade;
this.fabricacao;
console.log(this.nome, this.unidade, this.quantidade, this.preco, this.validade, this.fabricacao);
}
This isn't an Angular error. It's a JavaScript runtime error thrown by the JSON.stringify function. The error tells you that itens contains a circular object reference. This is OK while you run the application, but when stringifying it causes a problem: the JSON generated would become infinitely long.
As Kevin Koelzer indicated in his answer. The problem is that you wrote itens.unshift(itens);. Basically this adds the array of items to the array of items, thus creating a circular reference. Therefore, writing itens.unshift(item); instead solves your problem and is probably what you intended to do anyway.
itens.unshift(itens);
could this be:
itens.unshift(iten);
Related
I am receiving the following error when I call inside getStaticProps and I cannot figure out why:
Error: Error serializing `.lingo` returned from `getStaticProps` in "/".
Reason: `undefined` cannot be serialized as JSON.
I've placed the full app code on CodeSandbox. It won't be able to access the API but it does show where things are defined.
When I run the following query on GraphQL playground I get the expected response:
query {
allTerms {
id
term
slug
lead
}
}
You can see that this query is contained in lingo.service.js in the modules/lingo/services directory on the sandbox but the homepage has the Error serializing error. Is my function export async function getAll() not correct or am I calling it wrong in getStaticProps?
await getAll() is most likely returning undefined which is not serializable JSON. Defaulting to null would be one way to solve the issue.
export async function getStaticProps(context) {
return {
props: { lingo: (await getAll()) ?? null },
};
}
Right, this is supposed to be more of a comment but apparently I don't have enough reputation points to comment. So, I'll answer it like this.
Just check if your props (under getStaticProps()) are named correctly i.e. how they're named in the .json file you're trying to read. I ran into this issue because of a typo I had and just fixed it.
In Google Apps Script, I'm pulling data from an API. In the code below, the "output" variable contains an array of arrays. There is always at least one ["Response"] object, but sometimes there are 2.
My problem is, the code below isn't returning the second object (["Response"][1]) when it is present. I tried removing the "if" statement, but I get an error saying "TypeError: Cannot read property "Product" from undefined".
Does anyone know how to get the second object when it's present and ignore it when it's not?
var data = reportAPI();
var applications = data["applications"];
var output = []
applications.forEach(function(elem,i) {
output.push(["ID",elem["Id"]]);
output.push([elem["Response"][0]["Product"],elem["Response"][0]["Status"]]);
if (["Response"][1] != null) {
output.push([elem["Response"][1]["Product"],elem["Response"][1]["Status"]]);
}
}
P.S. I would even be happy with replacing the undefined object with "", but I'm not sure how to do it.
How about this modification? Please think of this as one of several answers. I used forEach to elem["Response"]. By this, values can be pushed by the number of elem["Response"].
From :
applications.forEach(function(elem,i) {
output.push(["ID",elem["Id"]]);
output.push([elem["Response"][0]["Product"],elem["Response"][0]["Status"]]);
if (["Response"][1] != null) {
output.push([elem["Response"][1]["Product"],elem["Response"][1]["Status"]]);
}
}
To :
applications.forEach(function(elem) {
output.push(["ID",elem["Id"]]);
elem["Response"].forEach(function(elem2) {
output.push([elem2["Product"],elem2["Status"]]);
});
});
If this didn't work, please tell me. I would like to modify.
The example below helps to account for the cases where the Response[0] or Reponse[1] are not "undefined" or "null". Putting !() will turn the Boolean values for "undefined" or "null" to true.
applications.forEach(function(elem,i) {
output.push(["ID",elem.Id]);
if(!(elem.Reponse[0]))
output.push([elem.Response[0].Product,elem.Response[0].Status]);
if (!(elem.Response[1])) {
output.push([elem.Response[1].Product,elem.Response[1]Status]);
}
}
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.
I would like to extend the native JSON object of node.js. In my example, I was able to extend it to add a merge(json1, json2) function, which merges 2 JSONs:
JSON.merge = function(target) {
var sources = [].slice.call(arguments, 1);
sources.forEach(function (source) {
for (var prop in source) {
target[prop] = source[prop];
}
});
return target;
}
This script is larglely inspired from this question: Combine or merge JSON on node.js without jQuery
To have a cleaner code, I put this script in a library folder, and require it in my main script. This is what I did...
My lib/JSON.js file:
extends.merge = function(target){
// The same script as above.
}
and in my app.js file:
JSON = require('./lib/JSON')
It works well, but now, native JSON methods don't work (like .stringify). Then I digged a little bit, and tried to extend JSON using .prototype, like this (in lib/JSON.js):
extends.prototype.merge = ...
But get the following error:
TypeError: Cannot set property 'merge' of undefined
I really don't know what to do (and what I'm doing) since solving a problems causes another problem.
Please, need help.
Thanks.
Good evening everyone. I am currently using MVC 3 and I have a viewmodel that contains a property that is a List. I am currently using json2's JSON.stringify method to pass my viewmodel to my action method. While debugging I am noticing that all the simple properties are coming thru but the collection property is empty even though I know for sure that there is at least one object in the collection. I wanted to know if there is anyone that is running into the same issue. Below is the code that I am using to post to the action method:
$.post("/ReservationWizard/AddVehicleToReservation/",
JSON.stringify('#ViewData["modelAsJSON"]'),
function (data) {
if (data != null) {
$("#vehicle-selection-container").html(data);
$(".reservation-wizard-step").fadeIn();
}
});
The object #ViewData["modelAsJSON"] contains the following json and is passed to my action method
{"NumberOfVehicles":1,"VehiclesToService":[{"VehicleMakeId":0,"VehicleModelId":0}]}
As you can see the property "VehiclesToService" has one object but when it gets to my action method it is not translated to the corresponding object in the collection, but rather the collection is empty.
If anyone has any insight into this issue it would be greatly appreciated.
Thanks in advance.
UPDATE
OK after making the recommended changes and making the call to new JavaScriptSerializer().Serialize(#Model) this is the string that ultimately gets sent to my action method through the post
'{"NumberOfVehicles":1,"VehiclesToService":[{"VehicleMakeId":0,"VehicleModelId":0}]}'
I can debug and see the object that gets sent to my action method, but again the collection property is empty and I know that for sure there is at least one object in the collection.
The AddVehicleToReservation action method is declared as follows:
public ActionResult AddVehicleToReservation(VehicleSelection selections)
{
...
return PartialView("viewName", model);
}
Here's the problem:
JSON.stringify('#ViewData["modelAsJSON"]')
JSON.stringify is a client side function and you are passing as argument a list that's stored in the ViewData so I suppose that it ends up calling the .ToString() and you have
JSON.stringify('System.Collections.Generic.List<Foo>')
in your final HTML which obviously doesn't make much sense. Also don't forget that in order to pass parameters to the server using the $.post function the second parameter needs to be a javascript object which is not what JSON.stringify does (it generates a string). So you need to end up with HTML like this:
$.post(
'ReservationWizard/AddVehicleToReservation',
[ { id: 1, title: 'title 1' }, { id: 2, title: 'title 2' } ],
function (data) {
if (data != null) {
$('#vehicle-selection-container').html(data);
$('.reservation-wizard-step').fadeIn();
}
}
);
So to make this work you will first need to serialize this ViewData into JSON. You could use the JavaScriptSerializer class for this:
#{
var myList = new JavaScriptSerializer().Serialize(ViewData["modelAsJSON"]);
}
$.post(
'#Url.Action("AddVehicleToReservation", "ReservationWizard")',
// Don't use JSON.stringify: that makes JSON request and without
// proper content type header your sever won't be able to bind it
#myList,
function (data) {
if (data != null) {
$('#vehicle-selection-container').html(data);
$('.reservation-wizard-step').fadeIn();
}
}
);
And please don't use this ViewData. Make your views strongly typed and use view models.