I'm making a todo list. When first entering the item and adding it to the list, the server works great. It takes the parameters that the user selects and passes them into a list on the server that can be viewed by rendering Item.list(), that looks like so:
[{"class":"server.Item","id":1,"assignedTo":"User 1","comments":null,"completed":false,"creator":"User 1","name":"Task 1","priority":"1","type":"Personal"},
{"class":"server.Item","id":2,"assignedTo":"User 2","comments":null,"completed":false,"creator":"User 2","name":"Er","priority":"3","type":"Work"},
{"class":"server.Item","id":3,"assignedTo":"User 1","comments":null,"completed":false,"creator":"User 2","name":"Ga","priority":"1","type":"Work"}]
Now, the user then has the option to edit the task later. On the client side this works fine, but then I need the user to be able to save the new, updated task.
This is my current update function:
def updateList() {
def newItem = Item.findById(request.JSON.id)
newItem.assignedTo = request.JSON.assignedTo
newItem.comments = request.JSON.comments
newItem.completed = request.JSON.completed
newItem.creator = request.JSON.creator
newItem.name = request.JSON.name
newItem.priority = request.JSON.priority
newItem.type = request.JSON.type
newItem.save(flush: true)
render newItem as JSON
}
This doesn't work, however. I get a null pointer exception that says "Cannot set property "assignedTo" on null object. I'm assuming that the findById request is not getting anything for the JSON object, and thus there is no object to assign values to, however I don't know what the problem is considering the items are in fact being put into the Item.list().
This is called with the following JS function on the client side:
$scope.updateList = function() {
angular.forEach($scope.items, function (item) {
// serverList.save({command: 'updateList'}, item);
$http.post('http://localhost:8080/server/todoList/updateList', item)
.success(function(response) {})
.error(function(response) {alert("Failed to update");});
});
};
This might depend on your Grails version, but you should be able to do this:
def update(Item item) {
if (!item) {
// return a 404
} else {
// you should really use a service and not save
// in the controller
itemService.update(item)
respond item
}
}
Grails is smart enough look that item up since there is an ID in the JSON params, and populate the object correctly.
Sort of a work around for anyone else that may need to do this in a basic manner, what I've done that works is clear the list when "Update List" is clicked, then read back in the values that are currently in the client side list.
Grails:
def clearList() {
Item.executeUpdate('delete from Item')
render Item.list()
}
def updateList() {
def newItem = new Item(request.JSON)
newItem.save(flush:true)
render newItem as JSON
}
Javascript:
$scope.updateList = function() { // Update list on the server
serverList.get({command: 'clearList'});
angular.forEach($scope.items, function (item) {
serverList.save({command: 'updateList'}, item);
});
};
Related
So I have a pretty normal eventListener that listens to the incoming events.
addEventListener("fetch", event => {
event.respondWith(handleRequest(event.request))
})
It goes to the handleRequest, which does certain different tasks depending on the request.url.
async function handleRequest (request) {
var url = new URL(request.url);
if (url.pathname === '[some-domain-name]/[some-link]') {
var jsonResult = handleJSON();
return jsonResult;
} else {
return handleHTML();
}
The handleJSON() and the handleHTML() are two additional functions that I have set up. What I essentially want to do is add one more if condition that has the criteria based on the response from handleJSON(), i.e., if jsonResult = [somevalidvalue] run handleHMTL() else respond with "You haven't accessed /[some-link] yet.
So to summarize, if we go to [some-domain-name] it should respond with the sentence. Then once we access /[some-link] we get some kind of value in jsonResult AFTER WHICH if we go back to [some-domain-name] it should hit with the response from handleHTML(). Also if possible, I'd like to know how can I pass the value from jsonResult in to our handleHTML() function. This is the result in the jsonResult.
const body = JSON.stringify(links, null, 2)
return new Response(body, init)
I'm sorry if the information sounds too long and stretched out. I haven't used Cloudflare's worker before and I've been trying to figure out the little stuff of what goes where and what I can and can't do with it. Thank You!
Your code implies that handleJSON() returns a Response object, since you then return it as the response to the original request. Your question is a little unclear, but it sounds like you are saying that this response contains a JSON body, and you want to inspect that body in your code. So you could do something like:
let jsonResponse = handleJSON();
if (jsonResponse.ok) { // check status code is 200
let jsonValue = await jsonRespnose.json();
if (jsonValue.someFlag) {
return handleHTML();
}
}
Note that calling jsonResponse.json() consumes the response body. Therefore, you can no longer return the response after this point. If you decide you want to return the JSON response to the client after all, you'll need to reconstruct it, like:
jsonResponse = new Respnose(JSON.stringify(jsonValue), jsonResponse);
This recreates the response body, while copying over the status and headers from the original response.
I have done a service that gets a json file from the server with the translated values of the labels of my webapp. Seems to work fine:
mobilityApp.service('serveiTraduccions', function($resource) {
this.getTranslation = function($scope) {
var languageFilePath = 'traduccions/traduccio_en.json';
$resource(languageFilePath).get(function (data) {
$scope.translation = data;
});
};
});
What I am trying to do is acces that "$scope.translation" from my controler, I tried all and nothing worked. The object is saved in my $scope as you can see:
how can I get the values of the "registroBtnRegistro", "registroErrorRegistro" etc ?
Thanks in advance !
I tried:
console.log($scope.translation); -> undefined
console.log($scope['translation']); -> undefined
console.log($scope.translation.registroBtnRegistro); -> TypeError:
Cannot read property 'registroBtnRegistro' of undefined
console.log($scope.translation['registroBtnRegistro']); -> TypeError:
Cannot read property 'registroBtnRegistro' of undefined
Maybe you're trying to access these values from another $scope that not inherits the scope where you've created your translation model.
Try to assign this model directly to $rootScope, so you can access it from every scope:
mobilityApp.service('serveiTraduccions', function($resource, $rootScope) {
this.getTranslation = function() {
var languageFilePath = 'traduccions/traduccio_en.json';
$resource(languageFilePath).get(function (data) {
$rootScope.translation = data;
});
};
});
this answer is a blind attempt because your original post lacks basic information like the call from the controller.
we can refine it until we make it work.
First, you should be returning something from your method:
mobilityApp.service('serveiTraduccions', function($resource) {
this.getTranslation = function() {
var languageFilePath = 'traduccions/traduccio_en.json';
return $resource(languageFilePath);
};
});
You are using $resource but you might as well use basic $http.get(). at least it doesn't look like a restful api to me.
In any case, because it's an asynchronous request, it will not return the list of translated strings, but a resource "class" that allows methods like get, delete or the more general query():
from the docs: default methods are
{ 'get': {method:'GET'},
'save': {method:'POST'},
'query': {method:'GET', isArray:true},
'remove': {method:'DELETE'},
'delete': {method:'DELETE'} };
sidenote: injecting $scope in a service doesn't make much sense to me: services are used to encapsulate common logic accross components. However, you can pass a scope instance as a parameter.
Then, the controller that uses this should have the service injected and use a callback to get the results when they have arrived (asynchronous operation!):
TraduccioCtrl ... {
$scope.translation = {}; // avoid undefined when the view just loads
ServeiTraduccions.getTranslation.query(function (response) {
$scope.translation = response; // and angular's two-way data binding will probably do the rest
});
}
The Angular docs about ng-resource have a working example. Other questions in SO have addressed this already too, like Using AngularJS $resource to get data
Can some one help or explain to me how this works please?
i have in my view:
<script type="text/javascript">
var jqxhr = $.getJSON("<%= Url.Action("GetTrainingModulePoints" , "Home") %>", function (json) {
console.log(json);
});
</script>
GetTrainingModulePoints should return 4 rows each containing a value for interactiontype and a value for points
in the console log i just get [object object]?
how can i see what is in the variable json?
http://imageshack.us/photo/my-images/542/firebug.png/
thanks
Look at the Network tab in FireBug or similar javascript debugging tool. There you will see the AJAX request and all you have to do is expand the request and look at the response.
Here's for example how that might look like in FireBug for a sample AJAX request:
And if you click on the JSON tab you will see the output formatted as a JSON object where you could expand/collapse the properties.
If for some very weird reason you cannot use a javascript debugging tool in your web browser (I don't know even know how you could be developing a web application, but ...) you could use the JSON.stringify method that's built into modern browsers:
var jqxhr = $.getJSON("<%= Url.Action("GetTrainingModulePoints" , "Home") %>", function (json) {
alert(JSON.stringify(json));
});
And if you are not using a modern browser which doesn't have the JSON.stringify method natively built-in you could still reference the json2.js script to your page.
UPDATE:
OK, it seems that your confusion comes from the fact that you are getting {"success":true} whereas you were expecting to get the rows from your stored procedure. I know this because I answered your previous question.
Here's how your controller action look like:
[HttpGet]
public JsonResult GetTrainingModulePoints()
{
var currentUser = ZincService.GetUserForId(CurrentUser.UserId);
ZincService.TrainingService.GetTrainingModulePoints(currentUser.UserId);
return Json(new { success = true }, JsonRequestBehavior.AllowGet);
}
As you can see in this controller action you are always returning success = true. If you want to return the results from your stored procedure you could do this:
[HttpGet]
public JsonResult GetTrainingModulePoints()
{
var currentUser = ZincService.GetUserForId(CurrentUser.UserId);
var modulePoints = ZincService.TrainingService.GetTrainingModulePoints(currentUser.UserId);
return Json(
new {
success = true,
modulePoints = modulePoints
},
JsonRequestBehavior.AllowGet
);
}
Here I assume that your TrainingService.GetTrainingModulePoints method is actually returning some object. If this is not the case you will have to explain what those methods are doing and how do you expect to get the output.
I would like to know if any better way to create multiple collections fetching from a single big JSON file. I got a JSON file looks like this.
{
"Languages": [...],
"ProductTypes": [...],
"Menus": [...],
"Submenus": [...],
"SampleOne": [...],
"SampleTwo": [...],
"SampleMore": [...]
}
I am using the url/fetch to create each collection for each node of the JSON above.
var source = 'data/sample.json';
Languages.url = source;
Languages.fetch();
ProductTypes.url = source;
ProductTypes.fetch();
Menus.url = source;
Menus.fetch();
Submenus.url = source;
Submenus.fetch();
SampleOne.url = source;
SampleOne.fetch();
SampleTwo.url = source;
SampleTwo.fetch();
SampleMore.url = source;
SampleMore.fetch();
Any better solution for this?
Backbone is great for when your application fits the mold it provides. But don't be afraid to go around it when it makes sense for your application. It's a very small library. Making repetitive and duplicate GET requests just to fit backbone's mold is probably prohibitively inefficient. Check out jQuery.getJSON or your favorite basic AJAX library, paired with some basic metaprogramming as following:
//Put your real collection constructors here. Just examples.
var collections = {
Languages: Backbone.Collection.extend(),
ProductTypes: Backbone.Collection.extend(),
Menus: Backbone.Collection.extend()
};
function fetch() {
$.getJSON("/url/to/your/big.json", {
success: function (response) {
for (var name in collections) {
//Grab the list of raw json objects by name out of the response
//pass it to your collection's constructor
//and store a reference to your now-populated collection instance
//in your collection lookup object
collections[name] = new collections[name](response[name]);
}
}
});
}
fetch();
Once you've called fetch() and the asyn callback has completed, you can do things like collections.Menus.at(0) to get at the loaded model instances.
Your current approach, in addition to being pretty long, risks retrieving the large file multiple times (browser caching won't always work here, especially if the first request hasn't completed by the time you make the next one).
I think the easiest option here is to go with straight jQuery, rather than Backbone, then use .reset() on your collections:
$.get('data/sample.json', function(data) {
Languages.reset(data['Languages']);
ProductTypes.reset(data['ProductTypes']);
// etc
});
If you wanted to cut down on the redundant code, you can put your collections into a namespace like app and then do something like this (though it might be a bit too clever to be legible):
app.Languages = new LanguageCollection();
// etc
$.get('data/sample.json', function(data) {
_(['Languages', 'ProductTypes', ... ]).each(function(collection) {
app[collection].reset(data[collection]);
})
});
I think you can solve your need and still stay into the Backbone paradigm, I think an elegant solution that fits to me is create a Model that fetch the big JSON and uses it to fetch all the Collections in its change event:
var App = Backbone.Model.extend({
url: "http://myserver.com/data/sample.json",
initialize: function( opts ){
this.languages = new Languages();
this.productTypes = new ProductTypes();
// ...
this.on( "change", this.fetchCollections, this );
},
fetchCollections: function(){
this.languages.reset( this.get( "Languages" ) );
this.productTypes.reset( this.get( "ProductTypes" ) );
// ...
}
});
var myApp = new App();
myApp.fetch();
You have access to all your collections through:
myApp.languages
myApp.productTypes
...
You can easily do this with a parse method. Set up a model and create an attribute for each collection. There's nothing saying your model attribute has to be a single piece of data and can't be a collection.
When you run your fetch it will return back the entire response to a parse method that you can override by creating a parse function in your model. Something like:
parse: function(response) {
var myResponse = {};
_.each(response.data, function(value, key) {
myResponse[key] = new Backbone.Collection(value);
}
return myResponse;
}
You could also create new collections at a global level or into some other namespace if you'd rather not have them contained in a model, but that's up to you.
To get them from the model later you'd just have to do something like:
model.get('Languages');
backbone-relational provides a solution within backbone (without using jQuery.getJSON) which might make sense if you're already using it. Short answer at https://stackoverflow.com/a/11095675/70987 which I'd be happy to elaborate on if needed.
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.