I don't know why orderBy is not working with trackBy, it is making me crazy :(
Here is my HTML code:
<div class="blocks-container" ng-init="loadProjects()" ng-controller="buildMonitorController">
<div class="row">
<!-- <div> -->
<div class="col-xs-12 col-sm-6 col-md-3 col-lg-2 block animate"
ng-if="!errorDialogActive"
ng-repeat="build in builds.builds.build track by build._id | orderBy:'lastBuildDetails.startDate' : true"
ng-class="{'running': project.running ,'block-green': build._status ==='SUCCESS','block-red': build._status==='FAILURE'}"
id="{{build._id}}">
<div class="title-container"><p>{{build._buildTypeId}}</p></div>
<div class="update-container col-xs-12">
<time>{{ build.lastBuildDetails.startDate | date : 'dd.MM.yyyy H:mm:s'}}</time>
</div>
</div>
</div>
<!--</div>-->
<!-- Start error state dialog -->
<div ng-include src="'views/main/error-dialog.html'"></div>
Everytime give me the same result even if i change the order to reverse
And Here my AngularJS code:
$scope.refreshBuilds = function () {
$scope.errorList.length = 0
//#TODO remove this part right after the API is working
//Init
var suffix = '';
var randomnumber = Math.floor(Math.random() * 3);
//simulate mock by random number
switch (randomnumber) {
case 1:
suffix = '-success';
break;
case 2:
suffix = '-less';
break;
default:
break;
}
var url = 'mock/builds'+suffix+'.xml';
console.log('url: ' + url)
$http({
method: 'GET',
url: url,
headers: {
Authorization: 'Basic AAA'
}
}).success(function (data, status) {
//Recive builds from xml and reset scope
var buildsToFilter = new X2JS().xml_str2json(data);
$scope.errorDialogActive = false;
//filter builds which have a no build API detail status
if (buildsToFilter.builds.build !== undefined) {
angular.forEach(buildsToFilter.builds.build, function (build, index) {
$http({
method: 'GET',
url: 'mock/build-'+build._id+'.xml',
headers: {
Authorization: 'Basic AAA'
}
}).success(function (buildDetailData) {
$scope.errorDialogActive = false;
//push detail data into build array
buildsToFilter.builds.build[index].lastBuildDetails = new X2JS().xml_str2json(buildDetailData).build;
console.log(buildsToFilter.builds.build[index]);
}).error(function (data, status) {
$scope.errorDialogActive = true;
//remove build from index if no build detail was found
buildsToFilter.builds.build.splice(index, 1);
$scope.setError(status, '', '');
}).then(function () {
//after filtering builds to display, setup builds $scope for FrontEnd
$scope.builds = buildsToFilter;
});
});
} else {
}
}).error(function (data, status) {
//active dialog if error happens & set error
$scope.errorDialogActive = true;
$scope.setError(status, 'builds', '');
}).then(function () {
$timeout(function () {
$scope.finishedRequest = true;
}, 5000);
//refresh right after proceed and a little delay
$timeout(function () {
console.log('Starting refresh');
$scope.refreshBuilds();
}, 21000);
})
};
If You need more code please let me know
Try reading the docs. It doesn't appear you are using it correctly.
https://docs.angularjs.org/api/ng/filter/orderBy
The last argument can only be "reverse".
Move 'track by build._id' to the end of the expression (after orderBy).
ng-repeat="build in builds.builds.build track by build._id | orderBy:'lastBuildDetails.startDate'
Related
I'm building a silly little Football app. On the first page, I am trying to load the country's top division standings and the coming week's fixtures.
I retrieve the data, using a RESTful Web Service and so is done asynchronously. The table is fine, but not the fixtures.
There is an array of fixture objects, within them, there's a 'matchday' and 'status' property. If you look at the 'this.getFixtures' function, look at the success code block. What I am trying to do is only display the fixtures for a certain match day. If there is one game left to be played on a certain matchday, then I only want that fixture displayed. If not, display next matchday's fixtures.
The 'status' property typically has a value of 'SCHEDULED' or 'FINISHED'. In the success code block I am saying:
Loop through all fixtures retrieved.
If this fixture is scheduled, that means, we're on the matchday for this fixture.
In which case, break loop.
I am then trying to use that value outside the get method, but I keep getting undefined. Is there any way to access that value outside the success block?
I'll use the $scope.matchDay function as the filter.This will help me to only display scheduled fixtures in that matchday with ng-repeat.
Anyway, sorry for the long winded post, but here's the code:
HTML:
<div class="grid-x">
<div class="medium-8 medium-offset-2 cell">
<div id="premier-league-banner">
<div class="banner-shade">
<div class="grid-x">
<div class="medium-5 cell">
<table>
<tr ng-repeat="team in premierLeagueTable.standing | limitTo: 6">
<th>{{ $index + 1 }}</th>
<td><img class="prem-thumbnail" src="{{ team.crestURI }}" /></td>
<th>{{ team.teamName }}</th>
<th>{{ team.playedGames }}</th>
<th>{{ team.goalDifference }}</th>
<th>{{ team.points }}</th>
</tr>
</table>
</div>
<div class="medium-2 cell">
<img src="images/prem-logo.png" />
</div>
<div class="medium-5 cell">
<table>
<tr ng-repeat="fixture in premierLeagueFixtures.fixtures | filter:{matchday: 10}">
<th>{{fixture.homeTeamName}}</th>
<td>vs</td>
<th>{{fixture.awayTeamName}}</th>
</tr>
</table>
</div>
</div>
</div>
</div>
</div>
Angular JS
// MODULE
var quickEleven = angular.module('quickEleven', ['ngRoute', 'ngResource']);
// ROUTES
quickEleven.config(function ($routeProvider) {
$routeProvider
.when('/', {
templateUrl: 'pages/home.htm',
controller: 'homeController'
})
});
// CONTROLLERS
quickEleven.controller('homeController', ['$scope', '$resource', '$log', 'footballData', function($scope, $resource, $log, footballData) {
function getMonday(date) {
var day = date.getDay() || 7;
if( day !== 1 )
date.setHours(-24 * (day - 1));
return date;
}
function convertDate(date) {
var yyyy = date.getFullYear().toString();
var mm = (date.getMonth()+1).toString();
var dd = date.getDate().toString();
var mmChars = mm.split('');
var ddChars = dd.split('');
return yyyy + '-' + (mmChars[1]?mm:"0"+mmChars[0]) + '-' + (ddChars[1]?dd:"0"+ddChars[0]);
}
var thisMonday = getMonday(new Date);
var nextMonday = getMonday(new Date);
nextMonday.setDate(nextMonday.getDate() + 7);
$log.info("Boom! " + convertDate(thisMonday));
$log.info("For! " + convertDate(nextMonday));
$scope.premierLeagueTable = footballData.getLeagueTable("http://api.football-data.org/v1/competitions/:competitionId/leagueTable", 445);
//http://api.football-data.org/v1/competitions/:competitionId/fixtures?timeFrameStart=2018-03-01&timeFrameEnd=2018-03-05
//"http://api.football-data.org/v1/competitions/:competitionId/fixtures/?matchday=9"
$scope.premierLeagueFixtures = footballData.getFixtures("http://api.football-data.org/v1/competitions/:competitionId/fixtures?timeFrameStart=" + convertDate(thisMonday) + "&timeFrameEnd=" + convertDate(nextMonday), 445);
$log.info($scope.premierLeagueFixtures);
$log.info($scope.premierLeagueTable);
$scope.matchdayValue = 9;
$scope.matchDay = function() {
return footballData.getMatchday();
};
}]);
quickEleven.service('footballData', ['$resource', '$log', function($resource, $log) {
//Referring to the latest matchday with the status as 'SCHEDULED'
var self = this;
var test;
self.latestScheduledMatchday = 0;
self.getMatchday = function() {
$log.info("This is: " + test);
return self.latestScheduledMatchday;
}
this.getLeagueTable = function (footballUrl, compId) {
this.footballAPI =
$resource(footballUrl, {}, {
get: {
method: "GET",
headers: {
"X-Auth-Token": "f73808b698e84dccbe4886da3ea6e755"
}
}
})
.get({
competitionId: compId
}, function(data) {
this.fussball = data;
}, function(err) {
$log.error(err);
});
return this.footballAPI;
};
this.getFixtures = function (footballUrl, compId) {
// var self;
this.footballAPI =
$resource(footballUrl, {}, {
get: {
method: "GET",
headers: {
"X-Auth-Token": "f73808b698e84dccbe4886da3ea6e755"
}
}
})
.get({
competitionId: compId
}, function(data) {
// self = data.fixtures;
self.latestScheduledMatchday = data.fixtures[0].matchday
for (var i = 0; i < data.fixtures.length; i++) {
var fixture = data.fixtures[i];
if (fixture.status == 'SCHEDULED') {
test = fixture.matchday;
break;
}
}
$log.info("Dollar signs... " + test);
}, function(err) {
$log.error(err);
});
return this.footballAPI;
};
}]);
I see 2 issues so far. One on the note of undefined values is your service might not be getting implemented correctly. AFAIK you should be returning the service in the "function($resource, $log) {" function.
Here's how I'd change it (note I've not tested this)
quickEleven.service('footballData', ['$resource', '$log', function($resource, $log) {
//Referring to the latest matchday with the status as 'SCHEDULED'
var wrappedService = {};
var test;
var latestScheduledMatchday = 0;
var getMatchday = function() {
$log.info("This is: " + test);
return latestScheduledMatchday;
}
wrappedService.getLeagueTable = function (footballUrl, compId) {
wrappedService.footballAPI =
$resource(footballUrl, {}, {
get: {
method: "GET",
headers: {
"X-Auth-Token": "f73808b698e84dccbe4886da3ea6e755"
}
}
})
.get({
competitionId: compId
}, function(data) {
wrappedService.fussball = data;
}, function(err) {
$log.error(err);
});
return wrappedService.footballAPI;
};
wrappedService.getFixtures = function (footballUrl, compId) {
wrappedService.footballAPI =
$resource(footballUrl, {}, {
get: {
method: "GET",
headers: {
"X-Auth-Token": "f73808b698e84dccbe4886da3ea6e755"
}
}
})
.get({
competitionId: compId
}, function(data) {
latestScheduledMatchday = data.fixtures[0].matchday
for (var i = 0; i < data.fixtures.length; i++) {
var fixture = data.fixtures[i];
if (fixture.status == 'SCHEDULED') {
test = fixture.matchday;
break;
}
}
$log.info("Dollar signs... " + test);
}, function(err) {
$log.error(err);
});
return wrappedService.footballAPI;
};
return wrappedService;
}]);
So instead of the function returning no service, you have your service wrapped and returned as I believe you were intending. I also removed references to "self" since your intention there (internal service variables) is more eloquently handled with var scoping in the function.
Second issue that you will see once your service is working.
$scope.premierLeagueTable = footballData.getLeagueTable("http://api.football-data.org/v1/competitions/:competitionId/leagueTable", 445);
This line does not return the request data, but returns the request object. In fact by the time $scope.premierLeagueTable is set, the request hasn't even completed yet. What you do get is access to a promise that you can put a callback function in. See the angular resource documentation for more info, specifically the third example in the user-resource section where you see .$promise https://docs.angularjs.org/api/ngResource/service/$resource#user-resource.
Whatever functionality you want to apply the data return to should live inside that .$promise.then(...) callback. I'm not entirely sure if the promise in there receives the response data, or your callback return. You'll have to read further or experiment to find that out.
I have this app that users can select a list of faults from drop downs drilling down three levels, the issue I am having is when they are opening the item to edit, the first drop down populates on page load and has the selected item from the saved data, the second populates the options but does not select the any items, and the third the same.
controller:
.controller("Ctrl", function ($scope, $http) {
var urlString = systems.systems + "/getIssueCodes/" + Id.Id;
$http({
method: 'GET',
url: urlString,
dataType: "json"
}).then(function successCallback(response) {
var data = response;
if (data.data.name1 !== "") {
$scope.Fault = data.data.name1;
f1 = data.data.id1;
$scope.faultChangedLoad(f1, (data.data.id2 === null ? "" : data.data.id2));
$scope.Fault1 = data.data.name2;
}
if (data.data.name2 !== "") {
f2 = data.data.id2;
$scope.fault1ChangedLoad(f2, (data.data.name3 === null ? "" : data.data.name3));
}
if (data.data.name3 !== null) {
f3 = data.data.id3;
}
$scope.Desc = data.data.desc;
});
$scope.faultChangedLoad = function (Fault, selected) {
var urlStr = systems.systems + "/faultCodes/" + Fault;
$http({
method: 'GET',
url: urlStr,
dataType: "json"
}).then(function successCallback(response) {
$scope.fault1Codes = [];
if (response.data.length > 0) {
var ms4 = angular.element(document.querySelector('#Main-select4'));
ms4.removeClass("no-show");
ms4.addClass("item item-select");
var ms6 = angular.element(document.querySelector('#Main-select6'));
if (ms6.hasClass("item")) {
ms6.removeClass("item item-select");
ms6.addClass("no-show");
}
}
else {
var ms41 = angular.element(document.querySelector('#Main-select4'));
if (ms41.hasClass("item")) {
ms41.removeClass("item item-select");
ms41.addClass("no-show");
}
var ms61 = angular.element(document.querySelector('#Main-select6'));
if (ms61.hasClass("item")) {
ms61.removeClass("item item-select");
ms61.addClass("no-show");
}
}
$scope.fault1Codes = response.data;
$scope.Fault1 = selected;
});
}
$scope.fault1ChangedLoad = function (Fault, selected) {
$http({
method: 'GET',
url: systems.systems + "/faultCodes/" + Fault,
dataType: "json"
}).then(function successCallback(response) {
$scope.fault2Codes = [];
if (response.data.length > 0) {
var ms6 = angular.element(document.querySelector('#Main-select6'));
ms6.removeClass("no-show");
ms6.addClass("item item-select");
}
else {
var ms61 = angular.element(document.querySelector('#Main-select6'));
if (ms61.hasClass("item")) {
ms61.removeClass("item item-select");
ms61.addClass("no-show");
}
}
$scope.fault2Codes = response.data;
$scope.Fault2 = selected;
});
}
}
View:
<label class="item item-select" id="Main-select5">
<span class="input-label">Issue Code:</span>
<select ng-model="Fault" ng-change="faultChanged(Fault)">
<option ng-repeat="faultCode in faultCodes" ng-selected="faultCode.text === Fault" value="{{faultCode.value}}">{{faultCode.text}}</option>
</select>
</label>
<label class="no-show" id="Main-select4">
<span class="input-label"></span>
<select ng-model="Fault1" ng-change="fault1Changed(Fault1)">
<option ng-repeat="fault1Code in fault1Codes" ng-selected="fault1Code.text === Fault1" value="{{fault1Code.value}}">{{fault1Code.text}}</option>
</select>
</label>
<label class="no-show" id="Main-select6">
<span class="input-label"></span>
<select ng-model="Fault2">
<option ng-repeat="fault2Code in fault2Codes" ng-selected="fault2Code.text === Fault2" value="{{fault2Code.value}}">{{fault2Code.text}}</option>
</select>
</label>
<label class="item item-input" id="Main-textarea1">
<span class="input-label">Description:</span><input type="text" placeholder="Enter Description" ng-model="Desc">
</label>
I have looked everywhere for a solution, I have tried ng-options but that did not help.
Any help is appreciated,
Thank you
I found a working solution and I want to put it here in case someone else has the same issue.
I could not find any help so I went back to the books, after reading several chapters, I saw (not mentioned in requirements) a bit of code that displayed ng-value instead of value and I tried it, it worked and the data is being displayed.
Thank you
I have been able to successfully upload an image with a custom field template calling a function that handles the upload. It then gathers the return url and from there, i have no idea how to insert it back into the field for saving with the form.
Any help would be much appreciated :)
Here is my code:
var myApp = angular.module('myApp', ['ng-admin', 'backand', 'ngFileUpload']);
//myApp.directive('dashboardSummary', require('./dashboards/dashboardSummary'));
myApp.config(['BackandProvider', function(BackandProvider) {
BackandProvider.setAppName('');
BackandProvider.setSignUpToken('');
BackandProvider.setAnonymousToken('');
}]);
myApp.config(function(RestangularProvider) {
// add a response interceptor
RestangularProvider.addResponseInterceptor(function(data, operation, what, url, response, deferred) {
var extractedData;
// .. to look for getList operations
if (operation === "getList") {
// .. and handle the data and meta data
extractedData = data.data;
extractedData.meta = data.data.__metadata;
} else {
extractedData = data;
}
return extractedData;
});
});
myApp.config(['NgAdminConfigurationProvider','BackandProvider', function (nga, BackandProvider, $scope) {
// create an admin application
BackandProvider.setAppName('');
BackandProvider.setSignUpToken('');
BackandProvider.setAnonymousToken('');
var admin = nga.application('Pocket Release Admin Manager')
.baseApiUrl('https://api.backand.com/1/objects/'); // main API endpoint#
// Users
var user = nga.entity('users');
user.listView().fields([
nga.field('firstName').isDetailLink(true),
nga.field('lastName'),
nga.field('email')
]);
user.creationView().fields([
nga.field('firstName'),
nga.field('lastName'),
nga.field('email', 'email')
]);
user.editionView().fields(user.creationView().fields());
// add the user entity to the admin application
admin.addEntity(user);
// Platforms
var platforms = nga.entity('platforms');
platforms.listView().fields([
nga.field('id'),
nga.field('platform_name'),
]);
platforms.creationView().fields([
nga.field('id'),
nga.field('platform_name'),
nga.field('platform_id')
]);
platforms.editionView().fields(platforms.creationView().fields());
admin.addEntity(platforms);
var data = {};
// Games
var games = nga.entity('games');
games.listView().fields([
nga.field('id'),
nga.field('game_title').isDetailLink(true),
nga.field('game_url'),
nga.field('platforms', 'reference')
.targetEntity(platforms)
.targetField(nga.field('platform_name'))
.label('Platform')
]);
games.creationView().fields([
nga.field('game_title'),
nga.field('image').template('<img ng-src="{{game_url}}" ng-show="game_url">'),
nga.field('game_url', 'file').uploadInformation({'url':'', 'apifilename':'game_url'}).template('<div ng-controller="main"><label class="btn btn-default btn-file">Browse<input id="fileInput" field="::field" value="entry.values[{{main}}]" entry="entry" entity="::entity" form="formController.form" datastore="::formController.dataStore" type="file" style="display: none;" accept="*/*" ng-click="initUpload()" /></label></div>', true),
nga.field('platforms'),
nga.field('game_description'),
nga.field('game_boxart'),
nga.field('game_release_uk', 'date'),
nga.field('game_release_us', 'date'),
nga.field('game_release_eu', 'date')
]);
games.editionView().fields(games.creationView().fields());
admin.addEntity(games);
// Dash
admin.dashboard(nga.dashboard()
.addCollection(nga.collection(games)
.name('total_games')
.title('Total Games')
.fields([
nga.field('game_title')
])
.sortField('game_title')
.sortDir('DESC')
.order(1)
).template(`
<div class="row dashboard-starter"></div>
<dashboard-summary></dashboard-summary>
<div class="row dashboard-content">
<div class="col-lg-6">
<div class="panel panel-default">
<ma-dashboard-panel collection="dashboardController.collections.total_games" entries="dashboardController.entries.total_games" datastore="dashboardController.datastore"></ma-dashboard-panel>
</div>
</div>
</div>
`));
// Menu Customize
// customize menu
admin.menu(nga.menu()
.addChild(nga.menu(user).icon('<span class="glyphicon glyphicon-file"></span> ')) // customize the entity menu icon
.addChild(nga.menu(games).icon('<span class="glyphicon glyphicon-folder-open"></span> ')) // you can even use utf-8 symbols!
.addChild(nga.menu(platforms).icon('<span class="glyphicon glyphicon-tags"></span> '))
);
// attach the admin application to the DOM and execute it
nga.configure(admin);
}]);
myApp.controller('main', function ($scope, $rootScope, $location, $http, Backand) {
// Image upload stuff
$scope.initUpload = function(){
var fileInput = document.getElementById('fileInput');
fileInput.addEventListener('change', function(e) {
imageChanged(fileInput);
});
}
function imageChanged(fileInput) {
//read file content
var file = fileInput.files[0];
var reader = new FileReader();
reader.onload = function(e) {
upload(file.name, e.currentTarget.result).then(function(res) {
$scope.imageUrl = res.data.url;
$scope.filename = file.name;
return res.data.url;
}, function(err){
alert(err.data);
});
};
reader.readAsDataURL(file);
};
function upload(filename, filedata) {
// By calling the files action with POST method in will perform
// an upload of the file into Backand Storage
return $http({
method: 'POST',
url : Backand.getApiUrl()+'/1/objects/action/games',
params:{
"name": 'files'
},
headers: {
'Content-Type': 'application/json'
},
// you need to provide the file name and the file data
data: {
"filename": Math.floor(Date.now() / 1000) + ''+ filename.match(/\.[0-9a-z]+$/i),
"filedata": filedata.substr(filedata.indexOf(',') + 1, filedata.length) //need to remove the file prefix type
}
}).success(function(data, status, headers, config) {
//$scope.game_url = data.url;
//$("#game_url").addClass("ng-dirty ng-valid-parse ng-touched").removeClass("ng-pristine ng-untouched");
//$("#game_boxart").val(data.url).addClass("ng-dirty ng-valid-parse ng-touched").removeClass("ng-pristine ng-untouched");
return data.url;
});
};
});
Have you tried making a PUT call to backand in order to save this url in the relevant column?
return $http({
method: 'PUT',
url : Backand.getApiUrl()+'/1/objects/games/YOUR_GAME_ID',
headers: {
'Content-Type': 'application/json'
},
data: {
urlColumn:imageUrl
}
}).success(function(data, status, headers, config) {
.....
});
I have a Products REST API that looks like below. The first part of the JSON helps to get the Products info and with-in the same data contains product_features with ID i.e., 4 and the id_feature_value i.e., 2943. The complete code is posted at the end.
{
"products":[
{
"id":578,
"id_manufacturer":"24",
"available_later":"",
"associations":{
"product_features":[
{
"id":"4",
"id_feature_value":"2943"
}
]
}
}
]
}
At present I have created 3 services to get this information but there seems to some issue when it comes to print in the hybrid mobile app. It just prints the last item value in all the products. I tried using the sub ng-repeat but it throws angular iteration error.
I am creating hybrid mobile app out of my curiosity and not a developer (learning from forums) therefore I need some direction on 2 things
In the code where I am doing wrong causing it to print the last
value of Features and Feature Values only instead actual
Is it recommended to use 3 services or should I
combine into one considering this is a hybrid mobile app.
Appreciate.
var gos_AppObject = angular.module('gosApp')
.run(function ($http, CacheFactory) {
$http.defaults.cache = CacheFactory('defaultCache', {
maxAge: 15 * 60 * 1000, // Items added to this cache expire after 15 minutes
cacheFlushInterval: 60 * 60 * 1000, // This cache will clear itself every hour
deleteOnExpire: 'aggressive' // Items will be deleted from this cache when they expire
});
})
/*
1st Service - Main Products and called once the device is ready
For example.,
Product: Coke Can (Pack of 6)
*/
.service('svc_Products', ['$http', 'CacheFactory', '$q', function ($http, CacheFactory, $q) {
var baseURL = 'http://localhost/goslocal/api/';
var ws_key = 'ws_key=SE7ELRQWM2BLDWL21ZI87D5NK615CW26';
var resourceToAccess = 'products'
var baseParams = '&display=full&sort=[id_DESC]&filter[active]=[1]&output_format=JSON';
CacheFactory('productsList', {
maxAge: 15 * 60 * 1000, // Items added to this cache expire after 15 minutes
cacheFlushInterval: 60 * 60 * 1000, // This cache will clear itself every hour.
deleteOnExpire: 'aggressive' // Items will be deleted from this cache right when they expire.
});
return {
ws_Product: function (id) {
var deferred = $q.defer();
var start = new Date().getTime();
var productsList = CacheFactory.get('productsList');
// Now that control of inserting/removing from the cache is in our hands,
// we can interact with the data in "dataCache" outside of this context,
// e.g. Modify the data after it has been returned from the server and
// save those modifications to the cache.
if (productsList.get(id)) {
deferred.resolve(productsList.get(id));
}
else {
$http({
method: 'GET',
url: baseURL + '/' + resourceToAccess + '?' + ws_key + baseParams,
cache: true,
headers: { 'Content-Type': 'text/plain' } //or whatever type
})
.success(function (data) {
productsList.put(id, data);
deferred.resolve(data);
});
}
return deferred.promise;
}
};
}])
/*
2nd Service - Product Features i.e., 4 which will give the Feature Name
For example.,
Product: Coke Can (Pack of 6)
Feature Name: Weight
*/
.service('svc_ProductsFeatures', ['$http', 'CacheFactory', '$q', function ($http, CacheFactory, $q) {
var baseURL = 'http://localhost/goslocal/api/';
var ws_key = 'ws_key=SE7ELRQWM2BLDWL21ZI87D5NK615CW26';
var resourceToAccess = 'product_features'
var baseParams = '&output_format=JSON';
CacheFactory('productFeaturesList', {
maxAge: 15 * 60 * 1000, // Items added to this cache expire after 15 minutes
cacheFlushInterval: 60 * 60 * 1000, // This cache will clear itself every hour.
deleteOnExpire: 'aggressive' // Items will be deleted from this cache right when they expire.
});
return {
ws_ProductFeatures: function (id, intFeatureID) {
var deferred = $q.defer();
var start = new Date().getTime();
var productFeaturesList = CacheFactory.get('productFeaturesList');
if (productFeaturesList.get(id)) {
deferred.resolve(productFeaturesList.get(id));
}
else {
$http({
method: 'GET',
url: baseURL + '/' + resourceToAccess + '/' + intFeatureID + '?' + ws_key + baseParams,
cache: true,
headers: { 'Content-Type': 'text/plain' } //or whatever type
})
.success(function (data) {
productFeaturesList.put(id, data);
deferred.resolve(data);
});
}
return deferred.promise;
}
}
}])
/*
3rd Service Product Features Values - which will give the Product Feature Value
For example.,
Product: Coke Can (Pack of 6)
Feature: Weight
Feature Value: 6 x 300ml.
*/
.service('svc_ProductsFeatureValues', ['$http', 'CacheFactory', '$q', function ($http, CacheFactory, $q) {
var baseURL = 'http://localhost/goslocal/api/';
var ws_key = 'ws_key=SE7ELRQWM2BLDWL21ZI87D5NK615CW26';
var resourceToAccess = 'product_feature_values'
var baseParams = '&output_format=JSON';
CacheFactory('productFeaturesValuesList', {
maxAge: 15 * 60 * 1000, // Items added to this cache expire after 15 minutes
cacheFlushInterval: 60 * 60 * 1000, // This cache will clear itself every hour.
deleteOnExpire: 'aggressive' // Items will be deleted from this cache right when they expire.
});
return {
ws_ProductFeaturesValue: function (id, intFeatureValueID) {
var deferred = $q.defer();
var start = new Date().getTime();
var productFeaturesValuesList = CacheFactory.get('productFeaturesValuesList');
if (productFeaturesValuesList.get(id)) {
deferred.resolve(productFeaturesValuesList.get(id));
}
else {
$http({
method: 'GET',
url: baseURL + '/' + resourceToAccess + '/' + intFeatureValueID + '?' + ws_key + baseParams,
cache: true,
headers: { 'Content-Type': 'text/plain' } //or whatever type
})
.success(function (data) {
productFeaturesValuesList.put(id, data);
deferred.resolve(data);
});
}
return deferred.promise;
}
}
}]);
/*
Products Display Contoller to display it in the front-end
*/
gos_AppObject.controller('ProductsDisplayController', ['$scope', '$filter', 'svc_Products', 'svc_ProductsFeatures', 'svc_ProductsFeatureValues',
function ($scope, $filter, svc_Products, svc_ProductsFeatures, svc_ProductsFeatureValues)
{
var productsImageURL = 'http://localhost/goslocal/api/images/products';
$scope.productsLoader = {
loading: false,
};
$scope.listOfProductFeatures = [];
$scope.listOfProductFeaturesValue = [];
$scope.status = null;
$scope.listOfProducts = null;
$scope.selectedProductID = null;
/* to fetch the Main Products List by calling the Service */
$scope.fn_ListOfProducts = function () {
$scope.productsLoader.loading = true;
var hasItems = 0;
$scope.NoRecordPlaceholder = null;
/*
Calling Web Service to fetch the Products from Server by passing the
unique key for CacheFactory to cache the data
*/
svc_Products.ws_Product("key_ListOfProducts")
.then(function (data) {
if (data.products.length > 0) {
hasItems = 1;
$scope.listOfProducts = data.products;
}
else {
hasItems = 0;
};
// Once the results are out, hide the Spinner
$scope.productsLoader.loading = false;
if (hasItems === 1) {
$scope.NoRecordPlaceholder = true;
}
else {
$scope.NoRecordPlaceholder = false;
}
});
}
/* to build the Image URL. Doesn't call any Service */
$scope.buildImageURL = function (intProductID, intImageID) {
return src = productsImageURL + '/' + intProductID + '/' + intImageID + '?ws_key=SE7ELRQWM2BLDWL21ZI87D5NK615CW26';
};
/*
Retrieve the Product Features
For Example.,
Product: Coke Can (Pack of 6)
Feature Name: Weight
*/
$scope.RetrieveProductFeatures = function (intFeatureID) {
$scope.listOfProductFeatures = [];
if (intFeatureID.length > 0) {
svc_ProductsFeatures.ws_ProductFeatures("key_ListOfProductFeatures", intFeatureID)
.then(function (data) {
$scope.listOfProductFeatures = data.product_feature;
});
}
return;
};
/*
Retrieve the Product Features Values
For Example.,
Product: Coke Can (Pack of 6)
Feature Name: Weight
Feature Value: 6 x 330ml
*/
$scope.RetrieveProductFeaturesValues = function(intFeaturesValueID) {
$scope.listOfProductFeaturesValue = [];
if (intFeaturesValueID.length > 0) {
svc_ProductsFeatureValues.ws_ProductFeaturesValue("key_ListOfProductFeaturesValuess", intFeaturesValueID)
.then(function (data) {
$scope.listOfProductFeaturesValue = data.product_feature_value;
});
return $scope.listOfProductFeaturesValue;
}
};
function onDeviceReady() {
$scope.fn_ListOfProducts();
}
document.addEventListener('deviceready', onDeviceReady, false);
}]);
<ons-row ng-controller="ProductsDisplayController">
<div ng-show="productsLoader.loading" class="normalLoader padding5px">
<ons-icon icon="ion-load-c" spin="true"></ons-icon>
<span class="generalText">Fetching data please wait...</span>
</div>
<div id="productContainer">
<ons-col ng-repeat="prods in listOfProducts | filter:{new: true}" class="productColumn">
<ul class="productUL">
<li style="background-color: #ffffff; text-align: center;">
<div style="position: relative;">
<div id="productImageDIV">
<img ng-src="{{buildImageURL(prods.id, prods.id_default_image)}}"
alt="{{prods.name}}" class="productImage_List" />
</div>
<div class="productPriceDIV">
<span class="productPrice_List">
{{prods.price | currency}}
</span>
</div>
</div>
</li>
<li class="productName_List padding5px">{{prods.name}}</li>
<li class="productWeight_List padding5px">
<span ng-init="RetrieveProductFeatures(prods.associations.product_features[0].id)">
<b>{{listOfProductFeatures.name}} : </b>
</span>
<span ng-init="RetrieveProductFeaturesValues(prods.associations.product_features[0].id_feature_value)">
{{listOfProductFeaturesValue.value}}
</span>
</li>
<li class="padding5px">
<div>
<button class="button tappable">
<ons-icon icon="fa fa-shopping-cart"></ons-icon>
<span>Add to Cart</span>
</button>
<button class="button button--light tappable">
<ons-icon icon="fa fa-heart"></ons-icon>
</button>
</div>
</li>
</ul>
</ons-col>
</div>
<div ng-if="NoRecordPlaceholder===false" class="padding5px" style="width: 100%;">
<div style="text-align: center;">
<ons-icon icon="fa fa-thumbs-o-down fa-4x"></ons-icon>
<br />
<span style="font-size: 25px; text-align:center; width: 100%;" class="center">
No New Arrivals, check back again.
</span>
</div>
</div>
</ons-row>
I have a .net web service containg two methods getUserTasks & getAllTasks(noOfDays) both return valid Json Data. Have verified it with JSONLINT.
var app = angular.module('tasksApp', []);
app.controller('taskController', function($scope, $http, taskGroupFactory) {
$scope.LoadTasks = function(taskFilter, dateFilter) {
console.log(taskFilter + '-' + dateFilter);
if (taskFilter == 'Self') {
$scope.enableFilters = true;
//$scope.taskGroups = taskGroupFactory.getUserTasks();
var getUTasks = taskGroupFactory.getUserTasks();
getUTasks.then(
function(tasks) {
console.log("success");
$scope.taskGroups = tasks.data;
}, function(errorData) {
console.log("Error: " + errorData);
});
};
if (taskFilter == 'All') {
$scope.enableFilters = false;
var getAllTasks = taskGroupFactory.getAllUserTasks(dateFilter);
getAllTasks.then(
function(tasks) {
console.log("success");
$scope.taskGroups = tasks.data;
}, function(errorData) {
console.log("Error: " + errorData);
});
//$scope.taskGroups = taskGroupFactory.getAllUserTasks(dateFilter);
// $scope.taskGroups = taskGroupFactory.getAllUserTasks(dateFilter)
// .success(function (tasks) {
// console.log('success');
// $scope.taskGroups = tasks.data;
// })
// .error(function (error) {
// console.log(error);
// });
};
};
});
app.factory('taskGroupFactory', function($http) {
var factory = {};
var serviceUrl = '/_layouts/SP.TaskDashboard/WebService/TaskService.asmx';
factory.getUserTasks = function() {
//return $http.post(serviceUrl + '/GetMyTasks');
return $http({
method: 'post',
url: serviceUrl + '/GetMyTasks',
headers: {
"Content-Type": "application/json",
"Accept": "application/json"
}
});
};
factory.getAllUserTasks = function(taskDateFilter) {
//var serviceUrl = '/_layouts/SP.TaskDashboard/WebService/TaskService.asmx';
// return $http.post(serviceUrl + '/GetAllTasks', { dateFilter: taskDateFilter })
// .success(function (tasks) {
// return tasks;
// })
// .error(function(errorData) {
// return errorData;
// });
// return $http({
// method: 'post',
// url: serviceUrl + '/GetAllTasks',
// headers: { "Content-Type": "application/json", "Accept": "application/json" }
// });
return $http.post(serviceUrl + '/GetAllTasks', {
dateFilter: taskDateFilter
});
//[{"WebTitle": "Press Releases","WorkflowName": "","Tasks": [{"ID": 1,"Title": "Test","WebTitle": "Press Releases","Status": "Not Started","EncodedAbsoluteUrl": "http://sukcw-vwi-sps02:2010/","ItemLink": "PressReleases/WorkflowTasks/1_.000","WorkflowLink": "","WorkflowName": "","ListId": "9F8054AD-E8C4-47B7-B9DB-24FA05853F31","DueDate": "/Date(1422316800000)/","Created": "/Date(1421327050000)/","ParentItemTitle": "","Classification": "overdue"},{"ID": 2,"Title": "Another Test","WebTitle": "Press Releases","Status": "Not Started","EncodedAbsoluteUrl": "http://sukcw-vwi-sps02:2010/","ItemLink": "PressReleases/WorkflowTasks/2_.000","WorkflowLink": "","WorkflowName": "","ListId": "9F8054AD-E8C4-47B7-B9DB-24FA05853F31","DueDate": "/Date(1422057600000)/","Created": "/Date(1421746613000)/","ParentItemTitle": "","Classification": "overdue"}]}, {"WebTitle": "Test","WorkflowName": "test apprvl workflow","Tasks": [{"ID": 29,"Title": "Please approve 05live-ego","WebTitle": "Test","Status": "Not Started","EncodedAbsoluteUrl": "http://sukcw-vwi-sps02:2010/","ItemLink": "sites/responsive/test/WorkflowTasks/29_.000","WorkflowLink": "http://sukcw-vwi-sps02:2010/sites/responsive/test/Documents/05live-ego.jpg","WorkflowName": "test apprvl workflow","ListId": "6A288BE5-51DD-43BE-B036-4B4A73BFAA5C","DueDate": null,"Created": "/Date(1426854267000)/","ParentItemTitle": " 05live-ego","Classification": "upcoming"}]}]
};
return factory;
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="tasksApp">
<div ng-controller="taskController">
<button type="button" class="btn btn-info" ng-click="toggle()">Show Pending Tasks</button>
<div ng-hide="myVar">
<input type="radio" name="taskType" value="Self" ng-model="taskFilter" ng-change="LoadTasks(taskFilter, null)" />My Tasks
<input type="radio" name="taskType" value="All" ng-model="taskFilter" ng-change="LoadTasks(taskFilter,list_day_option)" />All Tasks
<span ng-hide="enableFilters"> show tasks created in last <select ng-options="o.id as o.name for o in list_day_options.data" ng-model="list_day_option" ng-change="LoadTasks(taskFilter,list_day_option)"></select></span>
<div class="btn-group legendWrapper" ng-init="classificationFilter='duetoday'">
Overdue
Due today
Upcoming
Show all
</div>
<div class="panel-group">
<div ng-repeat="t in taskGroups" ng-click="itemClicked($index)" class="panel panel-default">
<div class="panel-heading">
<h4 class="panel-title">{{t.WebTitle + '-' + '(' + filtered.length + ')'}}</h4>
</div>
<div ng-class="applyToggleClass($index)">
<div ng-repeat="tsk in t.Tasks | filter:t.Classification=getClassificationFilter() as filtered" ng-class="applyTskClass(tsk)">
<span>{{tsk.Title}} </span><span ng-class="applyStatusStyle(tsk)">{{tsk.Status}}</span>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
Method call to getUserTasks from factory works fine, where as method call to getAllUserTasks(dateFilter) raises syntax error. No error in fiddler, shows the valid json data!! with status 200 but when I debug the script control goes into error block doesnot reach success block :( I have different ways to invoke the service method with parameter but nothing works. As you can see in the comments, feel it is to do with the way I am calling the webservice or passing the parameter to $http.post, please help.
Thanks