failing to reset language selection after sync - kendo-ui

I am facing a problem which I am not aware how to resolve. Let me describe elaborately below:
I have a commonViewModel kendo class where event like save, cancel are written. I am facing problem with the save event of this class.
save: function () {
var that = this;
var routeLanguage = "";
that._showBackConfirmation(false);
that.set("isFormSubmitted", true);
console.log("form is valid, sending the save request!");
if (vm.get("languageTabsVm.selectedLanguage")) {
routeLanguage = "/" + vm.get("languageTabsVm.selectedLanguage");
}
else if (that.get("model.Languages") && that.get("model.Languages").length > 1) {
that.get("model.Languages").forEach(function (lang) {
if (lang.get("IsActive") === true) {
//sätt cv-visning till det språk jag senast redigerade på detta item
routeLanguage = "/" + lang.LanguageId;
}
});
}
//if i call the function _loadDefaultLanguageSelection here, it
// works. because, the datasource is not synced yet.
//Make sure the datasource are syncing changes to the server (includes all crud)
return that.dataSource.sync().fail(function (e) {
//i need to do something here to be in the same language tab. But
//as i am changing directly in to model, it is not possible. But
//saving directly to model is essential because that model is
//shared to other viewmodel for language tab synching purpose.
that.set("isFormSubmitted", false);
console.log("form rejected");
}).done(function () {
if (that.get("isPersonaldetail")) {
var name = that.get("model.Name");
if (name.length > 12)
name = name.substring(0, 11) + "...";
$("#profileName").text(name);
}
that.set("isFormSubmitted", false);
that.set("isSelected", false);
// it is called from here right now. but it is failing because
// model is updated but not synced in that function
that._loadDefaultLanguageSelection();
router.navigate(that.nextRoute + routeLanguage);
});
},
_loadDefaultLanguageSelection: function () {
var that = this;
if (that.get("model.Languages") && that.get("model.Languages").length > 1) {
that.get("model.Languages").forEach(function (lang) {
if (!that.get("isPersonaldetail")) {
lang.set("IsActive", lang.get("LanguageId") === vm.get("languageTabsVm.selectedLanguage"));
}
});
}
},
So, my question is, how can i resolve this problem. one solution is i will have to sync twice. that is not nice. So, I am looking for efficient solution.

Related

How do I retain filters in JqGrid whilst still getting remote data?

I'm using this demo to display text and dropdown list filters in the columns of a JqGrid. The grid has a remote data source and with each sort, filter, or page view etc, it grabs the data from the remote source.
The problem I am having is that when the new data arrives, the grid is refreshed, and the filters revert to default. I've looked at a few examples by Dr Oleg but I can't get it to work with remote data and persistence. Any setting of datatype to "local" or loadonce to true breaks the remote datasource.
Does anyone have any ideas of how to get this to work?
I've tried the following, but as I said, this stops the JqGrid from making API requests:
loadComplete: function () {
var $this = $(this);
var postfilt = $this.jqGrid('getGridParam', 'postData').filters;
var postsord = $this.jqGrid('getGridParam', 'postData').sord;
var postsort = $this.jqGrid('getGridParam', 'postData').sidx;
var postpage = $this.jqGrid('getGridParam', 'postData').page;
console.log(postfilt);
console.log(postsord);
console.log(postsort);
console.log(postsort);*/
if ($this.jqGrid("getGridParam", "datatype") === "json") {
setTimeout(function () {
$this.jqGrid("setGridParam", {
datatype: "local",
postData: { filters: postfilt, sord: postsord, sidx: postsort },
search: true
});
$this.trigger("reloadGrid", [{ page: postpage}]);
}, 25);
}
}
I think the issue has something to do with the select2 dropdown menus. Here you can see it destroys the filter menu and recreates it.
var options = colModelOptions, p, needRecreateSearchingToolbar = false;
if (options != null) {
for (p in options) {
if (options.hasOwnProperty(p)) {
if (options[p].edittype === "select") {
options[p].editoptions.dataInit = initSelect2;
}
if (options[p].stype === "select") {
options[p].searchoptions.dataInit = initSelect2;
}
$grid.jqGrid("setColProp", p, options[p]);
if (this.ftoolbar) { // filter toolbar exist
needRecreateSearchingToolbar = true;
}
}
}
if (needRecreateSearchingToolbar) {
$grid.jqGrid("destroyFilterToolbar");
$grid.jqGrid("filterToolbar", filterToolbarOptions);
}
}
If there was a way this could be done just once per JqGrid load rather than per every request, then that may be a step in the right direction.
The answer to this was quite simple, it just didn't present itself to me until the next morning. I simply wrapped the code that built the search bar in a boolean check, so that it only loaded once.
// somewhere in the class
var gridLoaded = false;
// and in the JqGrid initialization
loadComplete: function (response) {
if (!gridLoaded) {
var options = colModelOptions, p, needRecreateSearchingToolbar = false;
if (options != null) {
for (p in options) {
console.log(p);
if (options.hasOwnProperty(p)) {
if (options[p].edittype === "select") {
options[p].editoptions.dataInit = initSelect2;
}
if (options[p].stype === "select") {
options[p].searchoptions.dataInit = initSelect2;
}
$(this).jqGrid("setColProp", p, options[p]);
if (this.ftoolbar) { // filter toolbar exist
needRecreateSearchingToolbar = true;
}
}
}
if (needRecreateSearchingToolbar) {
$(this).jqGrid("destroyFilterToolbar");
$(this).jqGrid("filterToolbar", filterToolbarOptions);
}
}
gridLoaded = true;
}
}
Thanks again to Dr Oleg for the help.

Telerik RadEditor: Overriding Media Manager 'Save'

Searched for a similar question but cannot find anything as yet.
I have a RadEditor set up and I would like to override the event after the MediaManager file upload finishes so I can get the file and process it as i like. The FileBrowser I am using already has a 'prototype' but this is not leading me anywhere. I'm thinking it will be a JQuery/Javascript calls but I can't seem to find anything on the Telerik website.
Telerik.Web.UI.Editor.DialogControls.FileBrowser.prototype = {
initialize: function () {
this.set_insertButton($get("InsertButton"));
this.set_cancelButton($get("CancelButton"));
var previewer = this.get_previewerType();
var previewerType = eval("Telerik.Web.UI.Widgets." + previewer);
$create(previewerType, { "browser": this }, null, null, $get(previewer));
this.set_filePreviewer($find(previewer));
this.set_fileBrowser($find("RadFileExplorer1"));
Telerik.Web.UI.Editor.DialogControls.FileBrowser.callBaseMethod(this, 'initialize');
},
dispose: function () {
Telerik.Web.UI.Editor.DialogControls.FileBrowser.callBaseMethod(this, 'dispose');
this._insertButton = null;
this._cancelButton = null;
}
}
Fine the solution through http://demos.telerik.com/aspnet-ajax/editor/examples/onclientpastehtml/defaultcs.aspx
On the OnClientPasteHtml i do the following:
function OnClientPasteHtml(sender, args) {
var commandName = args.get_commandName();
var value = args.get_value();
if (commandName == "FlashManager") {
var object = document.createElement("object");
Telerik.Web.UI.Editor.Utils.setElementInnerHtml(object, value);
var movieObject = object.firstChild;
//object.firstChild.Movie //this is the url of the file just uploaded
args.set_value('Write custom html here');
}
else if (commandName == "MediaManager") {
}
}

AngularJs 2 promises inside a watch the second one never works

I have 2 lists in my application and the user is supposed to drag and drop items from one list to another.
When the user drops an element from one of the lists to the other list a request has to be made to the server side code to update a field in the database (SelectedForDiscussion).
This is the code in my controller:
$scope.$watch("questionsDiscuss", function (value) {
var question = $.Enumerable.From($scope.questionsDiscuss).Where(function (item) { return !item.SelectedForDiscussion }).FirstOrDefault()
if (question != undefined) {
questionSelectionService.UpdateQuestionSelectionStatus(question.Id, true)
.then(function (output) {
var question = $.Enumerable.From($scope.questionsDiscuss)
.Where(function (item) { return item.Id == output.data.questionId })
.FirstOrDefault();
var index = $.Enumerable.From($scope.questionsDiscuss).IndexOf(question);
if (question != undefined)
if (output.data.result != "success") {
$scope.questionsDiscuss.splice(index, 1);
$scope.questionsReceived.splice(0, 0, question);
}
else {
question.SelectedForDiscussion = true;
$scope.questionsDiscuss[index] = question;
}
});
}
else {
var question = $.Enumerable.From($scope.questionsReceived).Where(function (item) { return item.SelectedForDiscussion }).FirstOrDefault();
if (question != undefined) {
questionSelectionService.UpdateQuestionSelectionStatus(question.Id, false)
.then(function (output) {
var question = $.Enumerable.From($scope.questionsReceived)
.Where(function (item) { return item.Id == output.data.questionId })
.FirstOrDefault();
var index = $.Enumerable.From($scope.questionsReceived).IndexOf(question);
if (question != undefined)
if (output.data.result != "success") {
$scope.questionsReceived.splice(index, 1);
$scope.questionsDiscuss.splice(0, 0, question);
}
else {
question.SelectedForDiscussion = false;
$scope.questionsReceived[index] = question;
}
});
}
}
}, true);
I have 4 javascript breakpoint placed at the following lines within Firebug:
2 of them at the following lines:
if (question != undefined) {
One at:
var question = $.Enumerable.From($scope.questionsDiscuss)
.Where(function (item) {
return item.Id == output.data.questionId
})
.FirstOrDefault();
And the other at:
var question = $.Enumerable.From($scope.questionsReceived)
.Where(function (item) {
return item.Id == output.data.questionId
})
.FirstOrDefault();
The following happens:
The breakpoints at:
if (question != undefined) {
are always reached.
The breakpoint at
var question = $.Enumerable.From($scope.questionsDiscuss)
.Where(function (item) {
return item.Id == output.data.questionId
})
.FirstOrDefault();
is also reached.
The other is never reached.
Both responses are OK(response code 200).
Everything should work perfectly but the then clause in the second promise is never reached.
Can anyone tell me what I am doing wrong?
The serverside appplication is an ASP.NET MVC application written in C#.
Edit 1:
I figured out why this was happening and I have a work around for it. I am stil interested in an actual solution.
The problem is angularjs throws an error then swallows it when calling $http for the second time. The error is:
digest alredy in progress
I think this is because in my directive I have this code:
dndfunc = function (scope, element, attrs) {
// contains the args for this component
var args = attrs.dndBetweenList.split(',');
// contains the args for the target
var targetArgs = $('#' + args[1]).attr('dnd-between-list').split(',');
// variables used for dnd
var toUpdate;
var target;
var startIndex = -1;
// watch the model, so we always know what element
// is at a specific position
scope.$watch(args[0], function (value) {
toUpdate = value;
}, true);
// also watch for changes in the target list
scope.$watch(targetArgs[0], function (value) {
target = value;
}, true);
// use jquery to make the element sortable (dnd). This is called
// when the element is rendered
$(element[0]).sortable({
items: 'div',
start: function (event, ui) {
// on start we define where the item is dragged from
startIndex = ($(ui.item).index());
},
stop: function (event, ui) {
var newParent = ui.item[0].parentNode.id;
// on stop we determine the new index of the
// item and store it there
var newIndex = ($(ui.item).index());
var toMove = toUpdate[startIndex];
// we need to remove him from the configured model
toUpdate.splice(startIndex, 1);
if (newParent == args[1]) {
// and add it to the linked list
target.splice(newIndex, 0, toMove);
} else {
toUpdate.splice(newIndex, 0, toMove);
}
// we move items in the array, if we want
// to trigger an update in angular use $apply()
// since we're outside angulars lifecycle
scope.$apply(targetArgs[0]);
scope.$apply(args[0]);
},
connectWith: '#' + args[1]
})
}
And there are 2 calls to apply at the end which trigger a new digest cycle I think.
Anyway I fixed it by adding this call before the calls to apply:
if (scope.updateLists != undefined)
scope.updateLists();
And moved all the code from the watch into the updateLists function.
Also because people have mentioned the service as having something to do with it I am pasting the relevant code within it:
GetQuestionsReceived: function (eid, criteria, page, rows) {
var promise = this.GetQuestionsReceivedInternal(eid,criteria, page, rows).then(function (response) {
// The return value gets picked up by the then in the controller.
return response;
});
// Return the promise to the controller
return promise;
},
GetQuestionsReceivedInternal: function (eid, criteria, page, rows) {
return $http({ method: 'GET',
url: '../QuestionManagement/GetQuestions?eventId='+eid+'&page=1&rows=5&'+serialize(criteria)
}).
success(function (data, status, headers, config) {
// this callback will be called asynchronously
// when the response is available
results = data;
}).
error(function (data, status, headers, config) {
// called asynchronously if an error occurs
// or server returns response with an error status.
if (window.console && console.log) {
console.log("Could not obtain questions received. Error:" + data + "Status:" + status + "Headers:" + headers + "Config:" + config);
}
});
},
GetQuestionsDiscuss: function (eid,criteria, page, rows) {
var promise = this.GetQuestionsDiscussInternal(eid,criteria, page, rows).then(function (response) {
// The return value gets picked up by the then in the controller.
return response;
});
// Return the promise to the controller
return promise;
},
GetQuestionsDiscussInternal: function (eid,criteria, page, rows) {
return $http({ method: 'GET',
url: '../QuestionManagement/GetQuestions?eventId=' + eid + '&page=1&rows=5&' + serialize(criteria)
}).
success(function (data, status, headers, config) {
// this callback will be called asynchronously
// when the response is available
response = data;
}).
error(function (data, status, headers, config) {
// called asynchronously if an error occurs
// or server returns response with an error status.
if (window.console && console.log) {
console.log("Could not obtain questions received. Error:" + data + "Status:" + status + "Headers:" + headers + "Config:" + config);
}
});
},
You have two very similar blocks of code, which could be generalized and placed in a function wrapper, leaving behind a very simple calling function.
If you can get everything into that form, then I think you will find it easier to debug.
Here is an attempt to do so :
function updateSelectionStatus(qA, qB, bool) {
var en = $.Enumerable.From(qA);
var question = en.Where(function (item) {
return bool ? !item.SelectedForDiscussion : item.SelectedForDiscussion;
}).FirstOrDefault();
if(question) {
questionSelectionService.UpdateQuestionSelectionStatus(question.Id, bool).then(function (output) {
if (output.data.result == "success") {
question.SelectedForDiscussion = bool;
}
else {
qA.splice(en.IndexOf(question), 1);
qB.unshift(question);
}
});
}
return question;
}
$scope.$watch("questionsDiscuss", function (value) {
if (!updateSelectionStatus($scope.questionsDiscuss, $scope.questionsReceived, true) {
updateSelectionStatus($scope.questionsReceived, $scope.questionsDiscuss, false);
}
}, true);
I may have made some false assumptions and simplified too much (eg. purging the inner $.Enumerable.From, which appears to reselect the same question as the outer), so you may well need to rework my code.
I'm advocating a principle here, rather than offering a solution.

hidding elements in a layout page mvc3

ok so im having a hard time hiding some layout sections (divs in my layout page and im using mvc3).
I have this js fragment which is basically the main logic:
$('.contentExpand').bind('click', function () {
$.cookie('right_container_visible', "false");
});
//Cookies Functions========================================================
//Cookie for showing the right container
if ($.cookie('right_container_visible') === 'false') {
if ($('#RightContainer:visible')) {
$('#RightContainer').hide();
}
$.cookie('right_container_visible', null);
} else {
if ($('#RightContainer:hidden')) {
$('#RightContainer').show();
}
}
as you can see, im hidding the container whenever i click into some links that have a specific css. This seems to work fine for simple tests. But when i start testing it like
.contentExpand click --> detail button click --> .contentExpand click --> [here unexpected issue: the line $.cookie('right_container_visible', null); is read but it doesnt set the vaule to null as if its ignoring it]
Im trying to understand whats the right logic to implement this. Anyone knows how i can solve this?
The simpliest solution is to create variable outside delegate of bind.
For example:
var rightContVisibility = $.cookie('right_container_visible');
$('.contentExpand').bind('click', function () {
$.cookie('right_container_visible', "false");
rightContVisibility = "false";
});
if (rightContVisibility === 'false') {
...
}
The best thing that worked for me was to create an event that can catch the resize of an element. I got this from another post but I dont remember which one. Anyway here is the code for the event:
//Event to catch rezising============================================================================
(function () {
var interval;
jQuery.event.special.contentchange = {
setup: function () {
var self = this,
$this = $(this),
$originalContent = $this.text();
interval = setInterval(function () {
if ($originalContent != $this.text()) {
$originalContent = $this.text();
jQuery.event.handle.call(self, { type: 'contentchange' });
}
}, 100);
},
teardown: function () {
clearInterval(interval);
}
};
})();
//=========================================================================================
//Function to resize the right container============================================================
(function ($) {
$.fn.fixRightContainer = function () {
this.each(function () {
var width = $(this).width();
var parentWidth = $(this).offsetParent().width();
var percent = Math.round(100 * width / parentWidth);
if (percent > 62) {
$('#RightContainer').remove();
}
});
};
})(jQuery);
//===================================================================================================

.bind() statement not working in jQuery Easy Confirmation plugin

Did anyone who used jQuery Easy Confirmation plugin run into this issue - the button upon which the confirm box is bound loses its original click event after the first click? I had to change the plugin code to this to make it work. The difference here is between .bind and .click. Can anyone explain why? Pls. let me know if my question is not clear. Thx!
Original plugin code:
// Re-bind old events
var rebindHandlers = function () {
if (target._handlers != undefined) {
jQuery.each(target._handlers, function () {
//this is the difference
$target.bind(type, this);
});
}
}
Changed (working) code:
// Re-bind old events
var rebindHandlers = function () {
if (target._handlers != undefined) {
jQuery.each(target._handlers, function () {
//this is the difference
if(type == 'click')
$target.click(this);
else {
$target.bind(type, this);
}
});
}
}
Try using some alerts to see what's happening...
// Re-bind old events
var rebindHandlers = function () {
if (target._handlers != undefined) {
jQuery.each(target._handlers, function () {
if(type == 'click')
alert('$target.click(' + this + ');');
//$target.click(this);
else {
alert('$target.bind(' + type + ', ' + this + ');');
//$target.bind(type, this);
}
});
}
}

Resources