Play 2.3/Angular JS $resource/routing issue - angularjs

So I'm trying to AJAX a single solr doc from my results list to a "doc view" view. I'm trying to use AngularJS to AJAX to my view render method and display the doc that way, but I can't seem to get the angular to work and I'm not sure I'm doing things correctly on the Play side either. Would you at least be willing to tell me if what I'm trying to do will work? The Angular error comes from the docText.text(); call. Here is my code:
Angular controller code:
var docText = $resource("http://localhost:9000/views/full-doc-text.html", {
text: {method: 'PUT'}
});
$scope.handleViewText = function(value) {
docText.text({doc: value});
}
Java code:
public static Result viewText() {
JsonNode json = request().body().asJson();
//do stuff here
return ok(viewtext.render(json));
}
route:
GET /views/full-doc-text.html controllers.Application.viewText()

I see three problems with the code above;
1.The definition of docText resource is not correct. if your read the angularjs manual here you'll see that $resource has 4 parameters. First one is resource url, second is parameter defaults, third one is custom actions and forth one is resource options where last three of them are optional. In your code you pass custom actions as the second parameter, which should be the third. And since you don't have any parameters in your resource url second parameter must be null. So first correction is:
var docText = $resource("http://localhost:9000/views/full-doc-text.html", null, {
text: {method: 'PUT'}
});
2.You define your text action's HTTP method as PUT however in your routes file you are handling GET requests for your desired action. You should change your route definition as:
PUT /views/full-doc-text.html controllers.Application.viewText()
3.PUT method is usually used for update operations when implementing a RESTFULL service. In your case you don't seem to be updating anything. So I suggest to use POST method just for convention.

Related

Value in view not updating after $promise is resolved

I have a value in my view that is not updating after a service method is called.
Here is the relevant code in the controller:
$scope.remaining = 20;
AcctService.getCurrentCount.get(calculateRemaining); //This is a $resource method
function calculateRemaining(result) {
$scope.remaining -= result;
alert($scope.remaining);
}
Here is the code for .getCurrentCount:
service.getCurrentCount = $resource('/api/getCount', {}, {
'get': { method: 'GET', isArray: true }
});
With the above code, say for example the result returned is 5. "15" will be alerted. However, in the view, {{remaining}} is still 20. No errors, the view just doesn't update.
I have tried the following:
$timeout - nothing different happens
Making $scope.remaining an object with property "value". (I read in another post about issues with data binding of primitives vs references). No difference.
$promise and .then() - no difference
$apply results in a digest error
Note, I am also coding with Ionic, not sure if it makes a difference. I disabled caching in the Ionic config, and another service method that returns an array propagates an ng-repeat as expected.
Thanks!
I'm not sure what things look like inside that get() function, but it doesn't look right.
Assuming get() returns a promise, you should write it like this:
AcctService.getCurrentCount.get().then(calculateRemaining); //This is a $resource method
First of all you do not need to create get method to return array. Use default 'query' method of $resource. And first parameter for the method is an object of parameters. second one is success function. So change you service to this
service.getCurrentCount = $resource('/api/getCount');
And later use it as
AcctService.getCurrentCount.query({},calculateRemaining);
Also check if you are not using one way data binding {{::remaining}}
And also you have to make sure you are using right $scope, to check that make "remaining" a field of an object. You can do it this way:
$scope.myData = {};
$scope.myData.remaining = 20;
and later at the controller initialize it the same and at the html
{{myData.remaining}}
also you can use $scope.apply(); but actually that is used at different case

Use dynamic parameters in Angular Resource

the Angular-Resource documentation says for parameters:
If any of the parameter value is a function, it will be executed every time when a param value needs to be obtained for a request (unless the param was overridden).
Unfortunately this does not work for me, the function is only called once when the resource is initialized.
My case:
I have a global Application state which you can choose on the top navigation of the app. This state affects a query param in most calls. (e.g. the date for which the call is valid). I maintain this global state in a service.
My Services (model layer) look like this:
function($resource, ApplicationState) {
return $resource('test/:_id', {
date: ApplicationState.getCurrentTime()
}, {
get: {
method: 'GET'
}
});
}
I'd expect ApplicationState.getCurrentTime() to be called on every get call. It is only called once.
I created a plunkr as an example. Open the Browsers Debug Console to see that ApplicationState.getCurrentTime() is only called once and not every time you click on the button.
http://plnkr.co/edit/qeoIUuzFCqnQNdnYp5ZX?p=preview
What do I do wrong? Is there a better way to inject dynamic parameters to some resources? I know the concept of request intereceptors, but I need this only on some services and not all.
Thanks for your help!
I found the answer with the help of frfancha on Github, the trick is to pass the function itself and not the result of the function.
See the missing brackets after ApplicationState.getCurrentTime here:
function($resource, ApplicationState) {
return $resource('test/:_id', {
date: ApplicationState.getCurrentTime
}, {
get: {
method: 'GET'
}
});
}
The function is now evaluated every time a request is made.
An updated Plnkr can be found here: http://plnkr.co/edit/Qx9HSsFwt5LDiM6Vmgff?p=preview
Credits go to frfrancha on Github

AngularJS $resource object doesn't provide an idempotent update method?

I've really be trying to wrap my head around this as much as possible, but having a very difficult time doing so. Maybe I'm missing the obvious.
Given a typical REST API (with an idempotent update method and a create method):
http://www.domain.com/api/clients GET // returns all clients
http://www.domain.com/api/clients POST // create a new client
http://www.domain.com/api/clients/:id GET // returns single client
http://www.domain.com/api/clients/:id PUT // updates a single client - idempotent
http://www.domain.com/api/clients/:id DELETE // delete single client
If I create a standard resource with the following URL:
Client = $resource("http://www.domain.com/api/clients/:id")
Then I automatically get (where Client is the $resource and client is the returned entity):
Client.get()
Client.query()
Client.save()
client.$save()
client.$remove/delete()
The problem I have is by default there is no PUT method to save (typically used to identify idempotent updates).
Am I misunderstanding something or is this a deficiency in Angular's API? I would have expected the $save() to use a PUT and not a POST. The way it is currently structured, I have to create my own $update() method definition and then rely on the developer not to accidentally use the $save() method.
Am I structuring my API incorrectly? Should the REST API be structured differently?
You can simply specify the method in your resource like :
app.factory('someFactory', ['$resource', function($resource) {
return $resource('/api/:id', {
id: '#id'
}, {
update: {
method: 'PUT'
},
get: {
method: 'GET'
}
});
}]);
but I totally agree with $save being an odd verb for create and not update. This guy does too and it looks like he made a way to dual purpose the save by simply extending the object and checking for an id.

ExtJs determine visibility on form load

In Extjs 3.4 I have a fairly large form that is being populated from an ajax call via someForm.getForm().load({url: someplace, etc}) which is working flawlessly. The problem I can't seem to get around though, is that there are several comboboxes and checkboxes that determine if another field is visible and allowBlank.
As per the answer on a similar question I have tried using the actioncomplete event on the form but the fields do not have values at that point. I've also tried using the success event of the load() call but get the same issue.
Is there any other ways of getting this functionality from the form.load() call?
Edit - here is my load call:
var panel = Ext.getCmp('someFormID');
panel.getForm().load({
method: 'GET',
url: 'ajax_get_request.aspx?id=' + id,
success: function (form) {
// This will error: object is null or undefined
alert(form.findField('fieldID').getValue());
}
});
I'm relatively new to Extjs so maybe I'm just missing something here...
Not sure why hooking into success callback of Ext.form.BasicForm.load() fails for you, but I can propose an alternative approach.
I usually use explicit Ext.Ajax.request() call to load data into Ext.data.Record. Then in request()'s success callback I load data into form using Ext.form.BasicForm.loadRecord(). If you need to act upon loaded values, you can do it in the same callback.
I do it this way, because I like to have original values from the server stored somewhere aside.

Submit a URL as data in cakePHP

I am using cakePHP 1.26.
I got an Input Text box which contains a URL and I want to submit the URL and stored it in the Database using Jquery AJAX.
Here is the HTML part:
<input type="text" id="testing" value="https://stackoverflow.com/questions/ask">
This is the JQuery part:
var whatContent=$("#testing").val();
var curl="http://localhost:8080/test/grab/"+whatContent;
$.ajax({
type: "POST",
url: curl,
success: function(data) {
alert(data);}
});
This is the code for the Action in the Controller:
function grab($w=null){
if($w!=null){
return $w;
}
}
The code worked and I could see the Alert Message pop up, but there was something missing in the message. I mean I supposed to see the whole URL like this:
https://stackoverflow.com/questions/ask
But not, I just saw part of it instead:
http://stackoverflow.com
Later I altered the value in the Input Text box like this:
<input type="text" id="testing" value="https://stackoverflow.com/faq">
But again, the returned value was still
http://stackoverflow.com
cakePHP seemed to conside the URL as some parameters rather than a URL.
Please help
When you append the content to the end of your "curl" variable like you are, you are attempting to add it to be retrieved through a GET variable and will get a result in a request like http://localhost:8080/test/grab/http://stackoverflow.com/questions/ask. Clearly this is an invalid request. Your GET variable parsing is not going to be consistent and a dangerous way of passing data back to your controller (especially if users will be able to edit the appended value).
Instead, you should use the data attribute in jQuery to pass this information back in your POST request as described in the instructions here: http://api.jquery.com/jQuery.ajax/
On the Cake side, you'll be able to receive this value as $this->data['IDValueYouConfigured']. For example, if your AJAX request was like:
var whatContent=$("#testing").val();
var curl="http://localhost:8080/test/grab/";
$.ajax({
type: "POST",
url: curl,
data: "formValue="+whatContent,
success: function(data) {
alert(data);}
});
where formValue is the IDValueYouConfigured that I mentioned earlier.
More importantly, you seem to be misunderstanding proper use of the Cake framework and could be performing all of these functions MUCH more simply using things like the JsHelper, FormHelper, etc. I would recommend using the most RECENT version of Cake (1.3.3) and follow through the Blog tutorial at least once. This will lead to better questions which will be more likely to get helpful answers. Hope this helps.

Resources