Laravel 4 can't get data from Angular Ajax - javascript

I am trying to develop my application in Laravel 4 and Angular JS, my application allows user to retrieve their Information through the system via Text Change.
Angular is used to pass data input from the user to Laravel which in turn retrieves the Information from the Database.
However Laravel is unable to retrieve the data passed from Angular.
View
<div data-ng-controller="ReservationController">
<input id='ERI' type='text' data-ng-model="scanRID" data-ng-change="queryRes()" name='exampleInput' maxlength='3' />
</div>
Angular Factory
app.factory('exampleFactory', function($http) {
var factory = {};
factory.getExample = function(scanRID) {
return $http({
method: 'GET',
url: LARAVEL_CONTROLLER + 'Example',
data: $.param(scanRID)
});
};
return factory;
});
Angular Controller
app.controller('exampleController', function($scope, $http, exampleFactory) {
$scope.queryRes = function() {
if($scope.scanRID.length == 3) {
exampleFactory.getExample($scope.scanRID)
.success(function (data) {
// Do Something Here
})
.error(function (data) {
console.log(data);
});
}
};
});
Laravel 4 Routes
Route::get('Example', 'ExampleController#show');
Laravel 4 ExampleController
class ExampleController extends \BaseController {
public function show()
{
$id = Input::get('scanRID'); // This here might be wrong. It's always empty!
$data = ExampleModel::find($id); // Able to query and retrieve.
return Response::JSON($data); // Returns empty.
}
}
Laravel 4 ExampleModel
class ExampleModel extends Eloquent {
// The id of this table is what I want, but I can't retrieve it.
protected $fillable = ['id', 'ExampleData1', 'ExampleData2'];
protected $table = 'exampleTable';
}
I have searched everywhere for a solution, it seems that everyone is able to successfully make the Ajax call. I think there is something that I am missing out that I am unaware about.
I have also tried setting CSRF Token, but however, I do not think that is an issue. So my last resort is to turn to the experts and hope someone is able to help me.
On a side note, I am fairly new to Laravel and Angular, so if you do post a solution, please explain to me the issue as I would like to learn more about Angular and Laravel.
Thank you for reviewing my issue.

You are not passing the value of scanRID by scanRID parameter instead pass only the value without parameter. So you are try to get the value from scanRID using Input::get('scanRID'); but without having scanRID parameter. that should be the case ur not getting the value :)
return $http({
method: 'GET',
url: LARAVEL_CONTROLLER + 'Example',
data: $.param({scanRID:scanRID}) //Change Here
});
OR
return $http({
method: "GET",
url: LARAVEL_CONTROLLER + 'Example',
params: {scanRID:scanRID} //Change Here
);
change like this

Related

angular $resource not working as expected

I have a very simple address application in AngularJS. It connects to an API using $resource.
The ID I use is the mobilephone number of the person (I know it's not the best way to do it, but it's just an sample application to show a 3-tier application setup) So I've 2 pages with the same form:
The problem i'm facing is that it uses the same $resource for saving a new address and saving an edited address. When iḿ saving a new address it has to use the url http://127.0.0.1:5000/api/contacts/ without an id appended on it (the new ID it will get on the api/database side is the filled in mobile phone number)
When I edit an existing address and click the save button it has to use another url; http://127.0.0.1:5000/api/contacts/#mobilePhone.
So i've read the angular documentation on https://docs.angularjs.org/api/ngResource/service/$resource which states that you can override your paramDefaults in your actions. So that is what I try to do using this code:
$resource('http://127.0.0.1:5000/api/contacts/:id',{id:'#mobilePhone'},{
get: {
method: 'GET'
}, update: {
method: 'PUT'
}, save: {
method: 'POST',
id:''
}
},{});
which seems to be correct given the information. It appends the mobilePhone number on every GET and every PUT the get and update method respectively. When it calls the save method it should override the :id with an empty string, but it doesn't do that.
Clearly i'm doing something wrong.
If you need more code snipets let me know, I tried to keep it as clean as possible.
Update:
This is how I call the save method:
....
.controller('MovieCreateController',function($scope,$state,$stateParams,Movie){
$scope.movie=new Movie();
$scope.addMovie=function(){
$scope.movie.$save(function(){
$state.go('movies');
});
}
}
And this is the edit method:
....
.controller('MovieEditController',function($scope,$state,$stateParams,Movie){
$scope.updateMovie=function(){
$scope.movie.$update(function(){
$state.go('movies');
});
};
$scope.loadMovie=function(){
$scope.movie=Movie.get({id:$stateParams.id});
};
$scope.loadMovie();
});
There is not much code in your question, so I'll try to explain what you should do to use $resource.
Have a look at following code:
// The $resource service is a helper to create a 'constructor' function
// Contact below is a function
var Contact = $resource('http://127.0.0.1:5000/api/contact/:id',{id:'#mobilePhone'}, {
get: {
method: 'GET' // You don't need to override the GET
}, update: {
method: 'PUT'
}, save: {
method: 'POST'
}});
// Be sure to create an 'entity' from the Contact $resource
// The 'new' will create a $resource instance with $update, $save methods overridden methods
var contact = new Contact({name: 'foobar'});
contact.$save(); // Will send a POST request
contact.mobilePhone = 2; // This is your id !
contact.$update(); // Will send a PUT request
If your resources always have a RESTful representation, I suggest that you use, as per suggested at angular discussion on issue#9807:
resource.prototype.$save = function() {
if (this.id) {
return this.$update();
} else {
return this.$create();
}
};
..rather that always overriding your $resource methods.
This is how you need to call your save method
$scope.movie=new Movie();
$scope.addMovie=function(){
$scope.movie.$save(function(){
$state.go('movies');
});
}
This is how you need to call your edit method
$scope.movie=new Movie();
$scope.updateMovie=function(){
$scope.movie.$update({ "mobilePhone": $stateParams.id},function(){
$state.go('movies');
});
};
For that you need to create a factory for $resource.which is always recommendable
Try this
.factory('movie', ['$resource', function ($resource) {
return $resource('http://127.0.0.1:5000/api/contacts/:id',{id:'#mobilePhone'},{}, {
update: { method: 'PUT' },
query: {
method: 'GET',
isArray: false
}
})
}])
Inject your factory in your controller
.controller('MovieCreateController',['$scope','$state','$stateParams','movie',function($scope,$state,$stateParams,Movie){
}]);

Angular http request with custom data

I am trying to do a http request to a php file on my server. My code i am using at the moment is as follows:
App.controller('GetSales', ['$scope', '$http', function ($scope, $http) {
$http({
method: 'POST',
url: '/app/controller/apis/_sales.php?period_start=2015-07-01&period_end=2015-07-31&join=leads&status=0&category=0user=1'
})
.success(function (data) {
$scope.sales = data;
});
}]);
Isnt there a better way to do this?
When i add these var as data it doesnt get posted to my page?
data: {
period_start: '2015-07-01',
period_end: '2015-07-31',
join: 'leads',
status: '',
category: '',
user: '1'
};
In php i get the data like this, its also sanitized for security reason:
$user = filter_var($_REQUEST['user'], FILTER_SANITIZE_NUMBER_INT);
$period_start = $_REQUEST['period_start'].' 00:00:00';
At first sight you are tryng to call an HTTP POST service, but you send parameter like it was a GET service, try something like that:
App.controller('GetSales', ['$scope', '$http', function ($scope, $http) {
$http.post('/app/controller/apis/_sales.php',
{
period_start: '2015-07-01',
period_end: '2015-07-31',
join: 'leads',
status: '',
category: '',
user: '1'
})
.success(function (data) {
$scope.sales = data;
})
.error(function (data, status) {
console.log(status);
});
I would use json_decode( file_get_contents('php://input') ) on your serverside. Also, please don't forget to sanitize your user sent data!
var dataParams = {
period_start: '2015-07-01',
period_end: '2015-07-31',
join: 'leads',
status: '',
category: '',
user: '1'
};
App.controller('GetSales', ['$scope', '$http', function ($scope, $http) {
$http.post('/app/controller/apis/_sales.php', dataParams)
.success(function (data) {
$scope.sales = data;
});
}]);
You will want to watch ever using the variable data as it will most likely collide with another variable, such as in your demonstration where you have named your post params as data while the return response is also aliased as data in the $.post success. This may not cause an issue in this case - but it usually will, so I renamed it for you out of habit.
Your server side could look something like this depending on what your usernames strings consist of:
public static function sanatize_client_string($dirtyString){
$cleanString = htmlspecialchars(strtolower(preg_replace("/[^a-z]+/i", "[FORBIDDEN_CHAR]", $dirtyString)));
return $cleanString;
}
$client_data = sanatize_client_string(json_decode( file_get_contents('php://input')));
Now you can access the username like:
echo $client_data['user']; // Will echo 1 based on the post data you are sending
This is what a simple serverside data-router could look like, as using normal $_POST has never worked for Angular data for me either:
/**
* Collect all Angular HTTP Request data
*/
$client_data = json_decode( file_get_contents('php://input') );
$app_state = utils::sanatizeClientString($client_data->appState); // <- name of prop must match client angularPostObj.x = serverModel.x
/**
* Cache the view path to the model
*/
$module_exists_in_model = isset($app['view_data']['views'][$app_state]);
/**
* If the angular post request matches data in the model, return the requested dataset, while if no object is found
* under that address, the error object will be returned which will send and error data to the view.
*
* This error condition will never happen aside from an attack because the clientside AngularJS router would prevent any
* unregistered paths from being even sent to the server. This would happen using a post mocking service or by
* forcing the string change in the code inspector while using the site.
*/
$module_exists_in_model ?
$view_model = $app['view_data']['views'][$app_state] :
$view_model = $app['view_data']['views']['error'];
// Call the view from Angular post data, passing it to a Class that sends a response as valid JSON
Render_app::echo_json($view_model);
I was informed of this by: http://www.cleverweb.nl/javascript/a-simple-search-with-angularjs-and-php/ and How to post a data in Angular?.
The point is... use $client_data = json_decode( file_get_contents('php://input') ); instead of $client_data = $_POST['username'];

Reading data from $resource.get() in AngularJS

JSON/XML from REST
{
litm: "T00000245",
lotn: "00004"
}
<jdeSerials>
<litm>T00000245</litm>
<lotn>00004</lotn>
</jdeSerials>
AngularJS controller
//Searching a product with serial number/LOTN
$scope.searchProduct = function () {
var lotn = $scope.jdeSerials.lotn;
console.log("searchProduct---->" + lotn);//log-->searchProduct---->00004
$scope.JdeSerials = lotnService.get({id: lotn}, function() {
console.log($scope.jdeSerials);//log-->[object Object]
console.log($scope.jdeSerials.litm);//log-->undefined!!!!!
});
//var litm = $scope.jdeSerials.litm;
//$scope.jdeproduct = productService.get({id: litm});
};
AngularJS service
angular.module('lotnService', ['ngResource'])
.factory('lotnService', ['$resource',
function ($resource) {
console.log('------lotmService-----');
return $resource(
'http://localhost:8080/RMAServer/webresources/com.pako.entity.jdeserials/:id',
{},
{
update: { method: 'PUT', params: {id: '#lotn'} }
});
}]);
Question
How can I get a value to $scope.jdeSerials.litm? Is there any better idea to solve this like creating a service which handles this two GETs? I think that reason is the GET method is asynchronous, but what is the best solution to handle situations like this?
EDIT/update
I changed the service call like this:
$scope.JdeSerials = lotnService.get({id:lotn})
.$promise.then(function(jdeSerials) {
$scope.jdeSerials = jdeSerials;
console.log("1--------------->LITM:"+$scope.jdeSerials.litm);
});
I got the LITM, BUT I got the errormessage as well:
TypeError: Cannot read property 'then' of undefined
Try to create a get method in your resource.
angular.module('lotnService', ['ngResource'])
.factory('lotnService', ['$resource', function ($resource) {
return $resource( 'http://localhost:8080/RMAServer/webresources/com.pako.entity.jdeserials/:id',
{},
{
get: { method: 'GET', params: {id: '#lotn'}},
update: { method: 'PUT', params: {id: '#lotn'} }
});
}]);
Then in your controller, call method get from service:
lotnService.get({id:lotn}).$promise.then(
function(jdeSerials) {
$scope.jdeSerials = jdeSerials;
console.log("1--------------->LITM:"+$scope.jdeSerials.litm);
});
What angular js version are you using?
Does the following work ?
lotnService.get({id:lotn}).then(
function(jdeSerials) { ... }
);
(without the $promise)
I was browsing the docs and also angular-resource.js source for previous versions and it appears that the synthax has changed somewhere along the line.
On angular-resource.js 1.2.0 source:
The Resource instances and collection have these additional properties:
$promise: the {#link ng.$q promise} of the
original server interaction that created this * instance or
collection.
On 1.0.8 there is no mention of the $promise propery, however.

AngularJS - Check my implementation of resource factory

Just starting out on AngularJS & js (being a backend developer) and this is the first Javascript MVC framework which I have ever worked on so please go easy...
I have a restful json API which I would like to consume using AngularJS.
In order to implement this, I have created two factories, one singular for when a controller needs to query the factory with an id, and a plural factory for when id is not required.
e.g. below:
Controller to list all products:
app.controller('ProductController', function($scope, ProductsFactory) {
$scope.products = [];
init();
function init()
{
$scope.products = ProductsFactory.query();
}
});
Factories:
app.factory('ProductsFactory', function($resource) {
return $resource('/xxx/xxx/xxx/api/v1/product', {}, {
query: { method: 'GET', isArray: true },
create: { method: 'POST' }
});
});
app.factory('ProductFactory', function($resource) {
return $resource('/xxx/xxx/xxx/api/v1/product/:id', {}, {
show: { method: 'GET' },
update: { method: 'PUT', params: { id: '#id' } },
delete: { method: 'DELETE', params: { id: '#id' } }
});
});
Question 1: Am I implementing the resource factory correctly?
Question 2: Is there a way of just using one factory for Products? e.g. allowing the factory to decide that id is not necessary for query and create, but is required for show, update and delete methods?
Yes, you can use just 1 factory :
app.factory('ProductFactory', function($resource) {
return $resource('/xxx/xxx/xxx/api/v1/product/:id', { id : '#id'}, {
update: { method: 'PUT' },
});
});
You don't need to specify the 'params' object to every requests. Defining it for the $resource is often enough (but if you want to overwrite it of course you can use it).
Notice that you don't need to define the CRUD methods since the $resource already implements them (as stated in the doc : http://docs.angularjs.or/api/ngResource.$resource).
At the moment, you just need to define a custom method update if you want to use "PUT" but a pull request is opened (https://github.com/angular/angular.js/pull/3416) and I hope we can expect to see it implemented soon.

AngularJS Services (Update/Save)

New to AngularJS and trying to get a grasp of the framework, and trying to build a basic CRUD app. I can't seem to figure out what is needed to Update an existing record. Here is my service:
angular.module('appServices', ['ngResource']).
factory('App', function ($resource) {
var Item = $resource('App/:AppId', {
//Default parameters
AppId: '#id'
}, {
//Actions
query: {
method: 'GET',
isArray: true
},
getById: {
method: 'PUT'
},
update: {
method: 'POST'
}
});
return Item;
});
I can run a basic Get all query, and getById to populate an edit form, but that's where I'm stuck. Here is example code for getById
$scope.apps = App.query();
$scope.getEdit = function(AppId) {
App.getById({id:AppId}, function(app) {
$scope.original = app;
$scope.app = new App(app);
});
};
$scope.save = function() {
//What type of information should go here?
//Do I need to make changes to the appServices?
};
I guess, I'm just not sure what's next concerning Updating existing information, or how the "app" object gets passed to the API, can anyone point me in the right direction, or show me a quick update method?
This is a really messy way of handling save operations in angular. For one - you should not be using PUT operations for retrieval requests and secondly - all of this is already built-in to angular. See below.
var Item = $resource( 'App/Details/:AppId', { AppId: '#id' } );
var item = Item.get({ id: 1 }, function( data ) {
data.setAnothervalue = 'fake value';
data.$save();
);
What I'm doing here is retrieving an "Item" and then immediately saving it with new data once it's returned.
Angular JS provides a stack of defaults already, including query, save, remove/delete, get.etc. And for most RESTful APIs, you really shouldn't need to add much, if anything at all. See the resource docs for more information, particularly the information on defaults: http://docs.angularjs.org/api/ngResource.$resource
Additionally, once you get a handle on that - you may want to use $save for both create/update operations, but using POST/PUT (RESTful conventions). If you do, see my article that I wrote about not too long ago: http://kirkbushell.me/angular-js-using-ng-resource-in-a-more-restful-manner/
After doing a bit more research, and reviewing Daniel's link (thanks). I got it working.
Controller method:
$scope.save = function() {
$scope.app.update();
};
Service Factory:
var Item = $resource('App/Details/:AppId', {
//Default parameters
AppId: '#id'
}, {
//Actions
query: {
method: 'GET',
isArray: true
},
getById: {
method: 'PUT'
},
update: {
method: 'POST'
}
});
Item.prototype.update = function (cb) {
console.log(this.AppId);
return Item.update({ AppId: this.AppId },
angular.extend({}, this, { AppId: undefined }), cb);
};
return Item;

Categories

Resources