Kendo scheduler, newly created object ID is not saved in the datasource - angularjs

I tried to create an item on the API and return a value with new 'ScheduleID', When I did a trace, API does return a new ScheduleID in the newly created object, but ScheduleID is never saved in the dataSource. Anyone know why?
vm.schedulerOptions = {
date: new Date(classStartDate.getUTCFullYear(), classStartDate.getUTCMonth(), classStartDate.getUTCDate(), 0, 0, 0),
height: 600,
views: [
"day",
{type: "week", selected: true},
],
dataSource: {
transport: {
read: function (options) {
if ($stateParams.classId) {
scheduleDf.getScheduleByClassId($stateParams.classId).success(function (result) {
options.success(result);
}).error(function (err) {
options.error(err);
})
} else if ($stateParams.sectionId) {
scheduleDf.getScheduleBySectionId($stateParams.sectionId).success(function (result) {
options.success(result);
}).error(function (err) {
options.error(err);
})
}
},
create: function (options) {
options.data.ClassId = classInfor.data[0].ClassID;
options.data.AtLocationId = vm.locationCb.dataItem().LocationID;
options.data.ConfirmationNumber = vm.ConfirmationNumber;
scheduleDf.createSchedule(options.data).success(function (result) {
//vm.grid.dataSource.read();
options.success(result);
}).error(function (err) {
options.error(err);
})
},
update: function (options) {
if (!fromMovingBar) {
options.data.AtLocationId = vm.locationCb.dataItem().LocationID;
fromMovingBar = false;
}
scheduleDf.updateSchedule(options.data).success(function (result) {
vm.grid.dataSource.read();
options.success(result);
}).error(function (err) {
options.error(err);
})
},
destroy: function (options) {
scheduleDf.deleteSchedule(options.data.ScheduleID).success(function (result) {
vm.grid.dataSource.read();
options.success();
}).error(function (err) {
options.error(err);
})
}
},
schema: {
model: {
id: "ScheduleID",
fields: {
start: {type: "date", from: "FromTime"},
end: {type: "date", from: "ToTime"}
}
}
}
},
editable: {
template: '<div ng-include="' + "'/schedule/_schedule_editor.html'" + '"></div>',
create: false
},
edit: function (e) {
e.container.data("kendoWindow").center();
e.container.find(".k-edit-form-container").width("auto");
e.container.data("kendoWindow").wrapper.css({width: 700});
},
moveEnd: function (e) {
fromMovingBar = true;
},
resizeEnd: function (e) {
fromMovingBar = true;
},
resources: [{
field: 'SessionTypeID',
dataColorField: 'ColorCode',
dataValueField: 'SessionTypeID',
dataTextField: 'SessionTypeName',
dataSource: sessionTypes.data
}]
};

The reason for current behavior is that the response from the server is not formatted the same way as the "read" request. You should try to insert the record inside array. For more info you can check this help article.
Also I notice that the Scheduler have no timezone option set. Please note that the timezone option is highly recommended to be set - for more details you can check the new Timezones help article.

Related

Elasticsearch.js AngularJS autocomplete

I'm trying to implement an autocomplete feature using Elasticsearch, angularJS and bootstrap.
I've got inspired by this solution :
autocomplete/typeahead angularjs bootstrap on elasticsearch
This is my Angular code:
angular.module('cineAngularApp')
.service('client', function (esFactory) {
return esFactory({
host: 'localhost:9200',
apiVersion: '2.2',
log: 'trace'
});
});
angular.module('cineAngularApp')
.controller('AutocompleteCtrl', function ($scope,client) {
$scope.getResult = function(val){
return client.search({
index: 'autocomplete_test',
fields: 'city',
q: 'city:'+val
}).then(function (resp) {
var keywords = [];
for(var i in resp.hits.hits){
var fields = (resp.hits.hits[i]).fields["city"];
keywords.push(fields);
}
return keywords;
}, function (err) {
console.trace(err.message);
});
};
});
Here is my problem
The above code works fine when I use a simple query, but as soon as I change the query by adding body it doesn't work.
angular.module('cineAngularApp')
.controller('AutocompleteCtrl', function ($scope,client) {
$scope.getResult = function(val){
return client.search({
index: 'autocomplete_test',
fields: 'city',
body: {
query: {
match: {
city: val
}
}
}
}).then(function (resp) {
var keywords = [];
for(var i in resp.hits.hits){
var fields = (resp.hits.hits[i]).fields["city"];
keywords.push(fields);
}
return keywords;
}, function (err) {
console.trace(err.message);
});
};
});
I don't know if it can help but I've also noticed when debugging that it's not a POST request anymore but it's an OPTION one.
Thanks in advance for your help.
Try with this:
return client.search({
index: 'movies',
"fields": [ "title" ],
"body": { // Use body field on elasticsearch client library
"query": {
"query_string": {
"fields": ["title"],
"query": "title:"+val
}
}
}
}).then(function (resp) {
// ....
})

Factory that serves multiple resource in angular

I intend to return few resource from a factory, but unfortunately it failed in my case. It shows the error message Entry is not a function Scope.$scope.create.
This is working code with one resource:
angular.module('Entry').factory('Entry', function($resource) {
return $resource('/api/entries/:id', { id: '#_id' }, {
update: {
method: 'PUT'
}
});
});
$scope.create = function() {
var entry = new Entry({
});
entry.$save(function() {});
}
This is not working code after adding multiple resource:
angular.module('Entry').factory('Entry', function($resource) {
return {
'EntryA': $resource('/api/entries/:id', { id: '#_id' }, {
update: {
method: 'PUT'
}
}),
'EntryB': $resource('/api/entries/:id', { id: '#_id' }, {
update: {
method: 'PUT'
}
}),
};
});
$scope.create = function() {
var entry = new Entry({
});
entry.EntryA.$save(function() {});
}

Unit testing angular service is not calling with expected param

I am testing a cancelWebSiteBuyRequest function that makes a call to a put request. I have done this many times but for some reason here I keep getting the error:
Expected spy put to have been called with
[ '/:orgId/WebSites/:webSiteId/BuyRequests/:requestId/Cancel', { orgId : 19, webSiteId : 4, requestId : 5432 }, { message : 'this is my
campaign post' } ]
but actual calls were
[ '/:orgId/WebSites/:webSiteId/BuyRequests/:requestId/Cancel', { orgId : 19, webSiteId : 4, requestId : 5432 }, { message : { message :
'this is my campaign post' } } ].
I have done this the same way many times but I cannot find what I missed that causes the passed message to be called as the full object and not just the string I am pointing it too.
Function I am testing:
this.cancelWebSiteBuyRequest = function (orgId, webSiteId, requestId, message) {
var deferred = $q.defer();
apiResource.put('/:orgId/WebSites/:webSiteId/BuyRequests/:requestId/Cancel', { orgId: orgId, webSiteId: webSiteId, requestId: requestId }, { message: message })
.then(function (data, status, headers) {
deferred.resolve(data);
}, function (data, status, headers) {
deferred.reject("There was a problem canceling this buy request.");
});
return deferred.promise;
};
Test:
describe('webSiteBuyRequestService', function () {
beforeEach(module('pb.webSites.services'));
var mockApiResourceProvider;
var continuationToken = {
nextPartitionKey: 4352632,
nextRowKey: 613
};
var mockAccount = {
//entityId: 'r43',
//accountId: 436675,
orgId: 19,
page: 2,
length: 12,
requestId: 5432,
campaignId: 3215,
startDate: '05/02/25',
endDate: '06/24/15',
filterPath: '/:account/',
filterRegion: 'North Amarica',
webSiteId: 4,
message: { message: "this is my campaign post" },
buyRequestId: 5423
};
beforeEach(function () {
mockApiResourceProvider = {
hasError: false,
get: function (url, params) {
return {
then: function (callback, errorCallback) {
if (!mockApiResourceProvider.hasError) return callback(mockAccount);
return errorCallback();
}
};
},
post: function (url, params, data) {
return {
then: function (callback, errorCallback) {
if (!mockApiResourceProvider.hasError) return callback(data);
return errorCallback();
}
};
},
put: function (url, params, data) {
return {
then: function (callback, errorCallback) {
if (!mockApiResourceProvider.hasError) return callback(data);
return errorCallback();
}
};
},
delete: function (url, params) {
return {
then: function (callback, errorCallback) {
if (!mockApiResourceProvider.hasError) return callback();
return errorCallback();
}
};
}
};
module(function ($provide) {
$provide.value('apiResource', mockApiResourceProvider);
});
inject(function ($injector) {
webSiteBuyRequestService = $injector.get('webSiteBuyRequestService');
});
});
describe('cancelWebSiteBuyRequest() function', function () {
var baseURL = '/:orgId/WebSites/:webSiteId/BuyRequests/:requestId/Cancel';
var baseCall = { orgId: mockAccount.orgId, webSiteId: mockAccount.webSiteId, requestId: mockAccount.requestId };
it("with no error", function () {
spyOn(mockApiResourceProvider, "put").and.callThrough();
var result = webSiteBuyRequestService.cancelWebSiteBuyRequest(mockAccount.orgId, mockAccount.webSiteId, mockAccount.requestId, mockAccount.message);
expect(mockApiResourceProvider.put).toHaveBeenCalledWith(baseURL, baseCall, mockAccount.message);
expect(result.$$state.status).toEqual(1);
expect(result.$$state.value).toEqual(mockAccount.message);
});
});
Also if I change the code to use mockAccount.message.message it gives me the error
Expected spy put to have been called with [ >'/:orgId/WebSites/:webSiteId/BuyRequests/:requestId/Cancel', { orgId : 19, >webSiteId : 4, requestId : 5432 }, 'this is my campaign post' ] but actual >calls were [ '/:orgId/WebSites/:webSiteId/BuyRequests/:requestId/Cancel', { >orgId : 19, webSiteId : 4, requestId : 5432 }, { message : 'this is my campaign >post' } ].
Your product code is wrapping an object around the message you are sending in:
, { message: message }
You are then sending mockAccount.message as a parameter. So you end up with:
{ message: { message: 'this is my campaign post' }};
I think you want to send in mockAccount.message.message (just the text):
it("with no error", function () {
spyOn(mockApiResourceProvider, "put").and.callThrough();
var result = webSiteBuyRequestService.cancelWebSiteBuyRequest(mockAccount.orgId, mockAccount.webSiteId, mockAccount.requestId, mockAccount.message.message);
Then, inside the production code, you will wrap the text and produce:
{ message: 'this is my campaign post' }
Which will then match mockAccount.message;

Angular: How to return value from service method to scope variable

I have following service method with return statement.
this.partnersListForAutocomplete = function (container, options) {
$("#autocompletePartners").kendoAutoComplete({
dataSource : {
type: "json",
serverFiltering: true,
transport: {
read: function (options) {
console.log("List");
console.log(options.data);
requestParams = {
"entityName": "dvd",
"page": 1,
"pageSize": 20,
"filter": options.data.filter,
"sort": [
{
"field": "name",
"ord": "asc"
}
]
};
ApiService.doHttpRequest(
"POST",
$rootScope.apiBaseUrl + "partner/search",
requestParams
)
.success(function (data, status, headers, config) {
})
.error(function (data, status, headers, config) {
});
}
}
},
dataTextField: "name" ,
dataValueField: "id",
filter: "contains",
minLength: 1,
change : function (e) {
// I WANT RETURN IT
return "test";
},
select : function (e) {
// I WANT RETURN IT
return "test";
}
});
};
Which is called by this code from controller method:
selectedPartnerId = GlobalHelperService.partnersListForAutocomplete();
$scope.projectDetail.test = selectedPartnerId;
Problem is that returned value is not passed into selected scope.
How can i solve it please?
Note: Method for autocomplete is assync.
Thanks for any help.
You have a couple of options that I can think of from the top of my head:
You could return a promise from the partnersListForAutocomplete() method, and then inside your controller you would then do something like the following pseudocode:
GlobalHelperService.partnersListForAutocomplete()
.then(function(response) {
$scope.projectDetail.test = response;
});
Or, accept a callback to your partnersListForAutocomplete() method, and then inside your controller you would then do something like the following pseudocode:
GlobalHelperService.partnersListForAutocomplete(function(response) {
$scope.projectDetail.test = response;
});

Preload entire FuelUx tree in one ajax call

I am trying to use the FuelEx tree control. I do not want to load each node on the tree when the user selects the node. I would rather load the entire tree structure at the point the pages loads. I have a controller already built that builds the correct json for my entire tree.
Is there an example of how to preload the entire structure?
I am currently attempting to use the following as a starting point. I will convert it a Datasource object once I get it working correctly.
$('#myTree').tree({
dataSource: function(options, callback){
var self = this;
var param = null;
if ("type" in options && options.type == "folder") {
if ("dataAttributes" in options && "children" in options.dataAttributes) {
param = options.dataAttributes["id"];
}
}
debugger;
if (param != null) {
$.ajax({
url: "/bundle-picker-data",
//data: 'id=' + param,
type: 'GET',
dataType: 'json',
success: function (response) {
if (response.status == "OK")
callback({ data: response.data })
},
error: function (response) {
console.log(response);
}
})
}
setTimeout(function () {
callback({ data: [
{ name: 'Ascending and Descending', type: 'folder', dataAttributes: { id: 'folder1' } },
{ name: 'Sky and Water I (with custom icon)', type: 'item', dataAttributes: { id: 'item1', 'data-icon': 'glyphicon glyphicon-file' } },
{ name: 'Drawing Hands', type: 'folder', dataAttributes: { id: 'folder2' } },
{ name: 'Waterfall', type: 'item', dataAttributes: { id: 'item2' } },
{ name: 'Belvedere', type: 'folder', dataAttributes: { id: 'folder3' } },
{ name: 'Relativity (with custom icon)', type: 'item', dataAttributes: { id: 'item3', 'data-icon': 'glyphicon glyphicon-picture' } },
{ name: 'House of Stairs', type: 'folder', dataAttributes: { id: 'folder4' } },
{ name: 'Convex and Concave', type: 'item', dataAttributes: { id: 'item4' } }
]});
}, 400);
},
multiSelect: true,
cacheItems: true,
folderSelect: false,
});
$('#tree-selected-items').on('click', function () {
console.log("selected items: ", $('#MyTree').tree('selectedItems'));
});
$('#myTree').on('loaded', function (evt, data) {
console.log('tree content loaded');
});
$('#myTree').on('opened', function (evt, data) {
console.log('sub-folder opened: ', data);
});
$('#myTree').on('closed', function (evt, data) {
console.log('sub-folder closed: ', data);
});
$('#myTree').on('selected', function (evt, data) {
console.log('item selected: ', data);
});
Thanks,
Greg
You do not have to use the dataSource function to call an external API each time. You can call the external API the first time dataSource is run and return the top level folders in the callback's data object. Then, the next time, do not make the ajax request and index into the collection of all items object based on the folder opened.
If that was unclear, load the object with all the tree information once at the beginning and grab whatever children you need out of it when a folder is opened based on that folder's attributes.
You have to load items each time--there is no other way with this control, but the items can be cached in memory and do not require an external network request.

Resources