Angularjs RESTul Resource Request - rest

I am trying to make the request
....port/trimService/fragments/?fragment_name=:fragmentName
However if I try to make the "?fragment_name" a parameter, it breaks. As I am going to have more requests, my action with change so I cannot leave it in the url portion of the resource.
angular.module(foo).factory('FragmentService', ['$resource',
function ($resource)
{
var FragmentService = $resource('.../fragments/:action:fragmentName',
{},
{
'getFragments':
{
method: 'GET',
isArray: true,
params:
{
fragmentName: "#fragmentName",
action: "?fragment_name="
}
}
});
return FragmentService;
}
]);
As of right now, I have no idea what my URL is actually outputting.
EDIT: I changed my resource as /u/akonsu had mentioned below. I also added my controller as it is still not working correctly.
angular.module(foo).factory('FragmentService', ['$resource',
function ($resource)
{
var FragmentService = $resource('.../fragments/',
{},
{
'getFragments':
{
method: 'GET',
isArray: true,
params:
{
fragmentName: "#fragmentName",
}
}
});
return FragmentService;
}
]);
angular.module(foo).controller('FragmentController', ['$scope', 'FragmentService',
function ($scope, FragmentService)
{
$scope.fragmentQuery = {
fragmentName: 'a',
};
$scope.fragmentQuery.execute = function ()
{
if ($scope.fragmentQuery.fragmentName == '')
{
$scope.fragments = {};
}
else
{
$scope.fragments = FragmentService.getFragments(
{
fragmentName: $scope.fragmentQuery.fragmentName,
});
}
};
$scope.fragmentQuery.execute();
}
]);

Try omitting the query string altogether in the resource URL and just supply your fragmentName as a parameter to the action call. It should add it to the query string if it is not in the list of URL parameters.
$resource(".../port/trimService/fragments/").get({fragmentName: 'blah'})

Related

How to use URLs like '/update/:id' as KendoUI datasource?

I read the documentation but found nothing related to setting parameters in dataSource urls. Is it possible to achieve that?
Thx in advance.
Yes, it is possible. The urls defined in the DataSource.transport might be a function. This function receives (for update) as first argument the data being updated (the model) and returns the string that should be used as URL.
Composing the URL for what you want to do is:
var ds = new kendo.data.DataSource({
transport: {
read: {
url: function () {
return 'read';
}
},
update: {
url : function (item) {
return 'update/' + item.id;
}
}
}
});
The answer seems to be vague on 'item.'
Just note that 'item' is an object. In fact anything passed in to read has to be an object, that's what Kendo expects. If you pass anything else into read, like a string, it will convert it into an object which isn't what you want. So, the solution is as follows:
_viewModel: kendo.observable({
items: new kendo.data.DataSource({
transport: {
read: {
url: function (args) {
var urlParm = '?take=' + 1 + '&skip=0&page=1&pageSize=' + 1;
return CGI_ISD._base + 'api/executionsummary/executiondetails/' + args.msgId + urlParm;
},
dataType: "json"
},
},
schema: {
data: function (response) {
return response.AggregateData.Data;
}
}
}),
}),
_reload: function (msgId) {
this._viewModel.items.read({msgId: msgId});
}
Short answer:
Nope.
Long answer:
Parameters are passed either inline with the url parameter of the transport object...
var id = 'abc123';
var ds = new kendo.data.DataSource({
transport: {
read: {
url: 'api/employees?id=' + id
}
}
});
...or they are passed in the data parameter of the transport object.
var id = 'abc123';
var ds = new kendo.data.DataSource({
transport: {
read: {
url: 'api/employees',
data: {
id: id;
}
}
}
});
or
var id = 'abc123';
var ds = new kendo.data.DataSource({
transport: {
read: {
url: 'api/employees',
data: function () {
return { id : id };
}
}
}
});

Add new data from restful api to angularjs scope

I'm trying to create a list with endless scroll in angularjs. For this I need to fetch new data from an api and then append it to the existing results of a scope in angularjs. I have tried several methods, but none of them worked so far.
Currently this is my controller:
userControllers.controller('userListCtrl', ['$scope', 'User',
function($scope, User) {
$scope.users = User.query();
$scope.$watch('users');
$scope.orderProp = 'name';
window.addEventListener('scroll', function(event) {
if (document.body.offsetHeight < window.scrollY +
document.documentElement.clientHeight + 300) {
var promise = user.query();
$scope.users = $scope.users.concat(promise);
}
}, false);
}
]);
And this is my service:
userServices.factory('User', ['$resource',
function($resource) {
return $resource('api/users', {}, {
query: {
method: 'GET',
isArray: true
}
});
}
]);
How do I append new results to the scope instead of replacing the old ones?
I think you may need to use $scope.apply()
When the promise returns, because it isnt
Part of the angular execution loop.
Try something like:
User.query().then(function(){
$scope.apply(function(result){
// concat new users
});
});
The following code did the trick:
$scope.fetch = function() {
// Use User.query().$promise.then(...) to parse the results
User.query().$promise.then(function(result) {
for(var i in result) {
// There is more data in the result than just the users, so check types.
if(result[i] instanceof User) {
// Never concat and set the results, just append them.
$scope.users.push(result[i]);
}
}
});
};
window.addEventListener('scroll', function(event) {
if (document.body.offsetHeight < window.scrollY +
document.documentElement.clientHeight + 300) {
$scope.fetch();
}
}, false);

Angular.js - cascaded selects with AJAX loading

I have two selects: one for country, other for regions. Country select is filled statically, but region select has to be filled dependent on current country through POST request.
I already made a server method which responds to country parameter with corresponding JSON, made a code for loading data into the select, but when I put this code into a watch it does not work properly:
.....................
]).factory('helperService', [
'$http', '$log', function($http, console) {
var checkDiscount, getRegions;
getRegions = function(countryCode) {
return $http({
method: 'POST',
url: '/api/regions/',
data: {
country_code: countryCode
}
});
};
.....................
]).controller('orderController', [
.....................
$scope.$watch('billing_country', function(value) {
helperService.getRegions($scope.country).success(function(result) {
$scope.regions = result;
return $scope.order.billing_state = $scope.regions[0];
});
return $scope.country = value;
});
Your call to factory must return an object, currently it isn't returning anything at all.
Change it to the following:
.factory('helperService', ['$http', '$log', function($http, console) {
var checkDiscount;
var service = {
getRegions: function(countryCode) {
return $http({ method: 'POST',
url: '/api/regions/',
data: { country_code: countryCode }
});
}
};
return service;
}])/****/
And then your call to helperService.getRegions will work.

How to reuse jquery-ui-autocomplete cached results when appending search term?

I have the following JS method to bind the jQuery UI autocomplete widget to a search text box. Everything works fine, including caching, except that I make unnecessary server calls when appending my search term because I don't reuse the just-retrieved results.
For example, searching for "ab" fetches some results from the server. Typing "c" after "ab" in the search box fetches "abc" results from the server, instead of reusing the cached "ab" results and omitting ones that don't match "abc".
I went down the path of manually looking up the "ab" search results, filtering them using a regex to select the "abc" subset, but this totally seems like I'm reinventing the wheel. What is the proper, canonical way to tell the widget to use the "ab" results, but filter them for the "abc" term and redisplay the shortened dropdown?
function bindSearchForm() {
"use strict";
var cache = new Object();
$('#search_text_field').autocomplete({
minLength: 2,
source: function (request, response) {
var term = request.term;
if (term in cache) {
response(cache[term]);
return;
}
$.ajax({type: 'POST',
dataType: 'json',
url: '/get_search_data',
data: {q: term},
success: function (data) {
cache[term] = data;
response(data);
}
});
});
}
Here's my "brute-force, reinventing the wheel" method, which is, for now, looking like the right solution.
function bindSearchForm() {
"use strict";
var cache = new Object();
var terms = new Array();
function cacheNewTerm(newTerm, results) {
// maintain a 10-term cache
if (terms.push(newTerm) > 10) {
delete cache[terms.shift()];
}
cache[newTerm] = results;
};
$('#search_text_field').autocomplete({
minLength: 2,
source: function (request, response) {
var term = request.term.toLowerCase();
if (term in cache) {
response(cache[term]);
return;
} else if (terms.length) {
var lastTerm = terms[terms.length - 1];
if (term.substring(0, lastTerm.length) === lastTerm) {
var results = new Array();
for (var i = 0; i < cache[lastTerm].length; i++) {
if (cache[lastTerm][i].label.toLowerCase().indexOf(term) !== -1) {
results.push(cache[lastTerm][i]);
}
}
response(results);
return;
}
}
$.ajax({type: 'POST',
dataType: 'json',
url: '/get_search_data',
data: {q: term},
success: function (data) {
cacheNewTerm(term, data);
response(data);
return;
}
});
});
}
If anyone wants a version that supports multiple entries in the text box then please see below:
$(function () {
function split(val) {
return val.split(/,\s*/);
}
function extractLast(term) {
return split(term).pop();
}
var cache = new Object();
var terms = new Array();
function cacheNewTerm(newTerm, results) {
// keep cache of 10 terms
if (terms.push(newTerm) > 10) {
delete cache[terms.shift()];
}
cache[newTerm] = results;
}
$("#searchTextField")
.on("keydown",
function (event) {
if (event.keyCode === $.ui.keyCode.TAB &&
$(this).autocomplete("instance").menu.active) {
event.preventDefault();
}
})
.autocomplete({
minLength: 2,
source: function (request, response) {
var term = extractLast(request.term.toLowerCase());
if (term in cache) {
response(cache[term]);
return;
} else if (terms.length) {
var lastTerm = terms[terms.length - 1];
console.log('LAst Term: ' + lastTerm);
if (term.substring(0, lastTerm.length) === lastTerm) {
var results = new Array();
for (var i = 0; i < cache[lastTerm].length; i++) {
console.log('Total cache[lastTerm[.length] = ' +
cache[lastTerm].length +
'....' +
i +
'-' +
lastTerm[i]);
console.log('Label-' + cache[lastTerm][i]);
var cachedItem = cache[lastTerm][i];
if (cachedItem != null) {
if (cachedItem.toLowerCase().indexOf(term) !== -1) {
results.push(cache[lastTerm][i]);
}
}
}
response(results);
return;
}
}
$.ajax({
url: '#Url.Action("GetSearchData", "Home")',
dataType: "json",
contentType: 'application/json, charset=utf-8',
data: {
term: extractLast(request.term)
},
success: function (data) {
cacheNewTerm(term, data);
response($.map(data,
function (item) {
return {
label: item
};
}));
},
error: function (xhr, status, error) {
alert(error);
}
});
},
search: function () {
var term = extractLast(this.value);
if (term.length < 2) {
return false;
}
},
focus: function () {
return false;
},
select: function (event, ui) {
var terms = split(this.value);
terms.pop();
terms.push(ui.item.value);
terms.push("");
this.value = terms.join(", ");
return false;
}
});

Decoding response error in extjs

I am doing the following stuff when a form is submitted. But I get this error:
Error decoding response: SyntaxError: syntax error
Here is my onSubmit success function:
onSubmit: function() {
var vals = this.form.getValues();
Ext.Ajax.request({
url: 'ticketSession.php',
jsonData: {
"function": "sessionTicket",
"parameters": {
"ticket": vals['ticket']
}
},
success: function( result, request ) {
var obj = Ext.decode( result.responseText );
if( obj.success ) {
//alert ('got here');
th.ticketWindow.hide();
Web.Dashboard.loadDefault();
}
},
Here is my ticketSession.php
<?php
function sessionTicket($ticket) {
if( $_REQUEST['ticket'] ) {
session_start();
$ticket = $_REQUEST['ticket'];
$_SESSION['ticket'] = $ticket;
echo("{'success':'true'}");
}
echo "{'failure':'true', 'Error':'No ticket Number found'}");
}
?>
I also modified my onsubmit function but didnt work:
Ext.Ajax.request({
url: 'ticketSession.php',
method: 'POST',
params: {
ticket: vals['ticket']
},
i am simply echoing this but I still get that error
echo("{'success':'true'}");
Maybe this can help you. It's a working example of an ajax-request which is nested in a handler.
var deleteFoldersUrl = '<?php echo $html->url('/trees/delete/') ?>';
function(){
var n = tree.getSelectionModel().getSelectedNode();
//FolderID
var params = {'folder_id':n['id']};
Ext.Ajax.request({
url:deleteFoldersUrl,
params:params,
success:function(response, request) {
if (response.responseText == '{success:false}'){
request.failure();
} else {
Ext.Msg.alert('Success);
}
},
failure:function() {
Ext.Msg.alert('Error');
}
});
}