I'm trying to open a Kendo UI kendoWindow from within an MVC View. I also use a Partial View as the content of the kendoWindow. Moreover, I use the Kendo UI MVVM pattern to bind my elements.
First let me to show you my main View and my pop-up Partial View (kendoWindow).
The important part of my main View (Parent) is as follows:
#{
ViewBag.Title = "My Main View";
Layout = "~/Views/Shared/_Layout.cshtml";
}
<script src="~/Scripts/ViewModel/main.js"></script>
<script src="~/Scripts/InitView/main.js"></script>
<script type="text/javascript">
var viewModel;
$(function () {
viewModel = initVm({
GetPartialContent_Url: '#Url.Action("GetPartialContent")'
});
initView(viewModel);
kendo.bind($("#container"), viewModel);
viewModel.Onread();
});
</script>
<div id="container">
<div id="Window-box"></div>
// Some other elements like the button which opens the kendoWindow are defined here.
</div>
My initVm is as follows:
function initVm(arg) {
var vm = kendo.observable({
onOpenKendoWindow: function () {
$("#Window-box").kendoWindow({
iframe: true,
content: arg.GetPartialContent_Url,
title: 'Some Title',
width: 500,
height: 'auto',
close: function (e) {
//Is it possible to get some data from kendoWindow (Partial View) here?
}
});
var dialog = $("#Window-box").data("kendoWindow");
dialog.maximize();
}
});
return vm;
}
Until now, I showed you the important parts of my main View. Now I want to show you the important parts of my kendoWindow (Partial View).
My Partial View which is used as the content of the kendoWindow is as follows:
#{
Layout = "~/Views/Shared/_PartialLayout.cshtml";
}
<script src="~/Scripts/ViewModel/partial.js"></script>
<script src="~/Scripts/InitView/partial.js"></script>
<script type="text/javascript">
var partialVM;
$(function () {
partialVM = initPartialVm({
GetTransactions_Url: '#Url.Action("GetTransactions", "Account")'
});
initPartialView(partialVM);
kendo.bind($("#container"), partialVM);
});
</script>
<div id="container">
<div id="gridTransactions"></div>
</div>
And my initPartialVm is as follows:
function initPartialVm(arg) {
var vm = kendo.observable({
onSelectTransaction: function () {
// KendoWindow should be closed here and passing some data from here to main View (close event of kendowWindow);
}
});
return vm;
}
Note: The 'gridTransactions' is a Kendo UI GridView (inside of kendoWindow - Partial View). Each rows of this grid has a select button and the 'onSelectTransaction' function is fired when each of these select buttons is clicked.
And finally, the main question is that, how can I close the kendowWindow by clicking each select button of the GridView and pass some data to the close event of the kendowWindow?
Yes it is possible. I found it much easier and a bit cleaner to wrap all the dialog functionality up into a dialog controller and extend it a bit in javascript.
Once the .js part is done it makes for a cleaner use. If you don't prefer to do this then look for the findDialog function below (it shows how get a handle to a dialog and call the close method on it).
As far as sending data on close, It would be easy to add a callback in the dialog to be called when the dialog is closed, supplied on invocation, then add a property in the widget to set the custom data to pass through in the dialogs close() back to the consumers event handler.
Also, please note I am no javascript expert, it took me longer than I would like to admit to work the bugs out of this but it has held up solidly for about 6 years. Feel free to offer suggestions.
In Bundle Config:
bundles.Add(new ScriptBundle("~/bundles/myCustom").Include(
...
"~/Scripts/MyCustom/MyCustomDialogs.js",
...
));
Where you register scripts:
#Scripts.Render("~/bundles/MyCustom")
In your index view or parent view :
<div id="_applicationDialogs"></div>
<div id="_mainAppContentLoadsHere"></div>
var _mainDialogController;
$(document).ready(function () {
...
_mainDialogController = $("#_applicationDialogs").kendoMyCustomDialogController().data("kendoMyCustomDialogController");
...
}
Where you want to invoke the dialog: SomePartial
function lnkDetailsOnClick(someID) {
_mainDialogController.createDialog({
dialogId: "frmUserDetail_" + someID,
modal: false,
title:"Daily Details",
pin: true,
height: 575,
width: 1025,
actions: ["Refresh", "Maximize", "Minimize", "Pin", "Close"],
url: '#Url.Action("SomePartialView", "SomeController")',
data:{
someID: someID,
dialogName:'frmUserDetail_'+ someID //NOTE : This will come back in the invoked partial as Model.DialogName so it can be dismissed with ease.
}
});
}
Dismissing the Dialog Inside of SomePartial :
#model MyModelThatHasTheDialogHandle
function btnClose_Click() {
var dialog = _mainDialogController.findDialog('#Model.DialogName');
dialog.close();
}
Now for the long .js file :
(function ($) {
var kendo = window.kendo,
ui = kendo.ui,
Widget = ui.Widget;
var MyCustomDialogController = Widget.extend({
init: function (element, options) {
var that = this;
Widget.fn.init.call(this, element, options);
that._create();
},
onResize: function () { },
options: {
modal: true,
dialogId: "dlgController1",
url: "",
data: null,
pin: false,
width: 300,
height: 300,
actions:["Close"],
title: "Information",
disableMaximize:false,
name: "MyCustomDialogController",
autosize: false,
onDialogClosed: null,
hideOnClose: false
},
_create: function () {
var that = this;
},
createDialog: function (options) {
var that = this;
var wrapperName = options.dialogId + "_wrapper";
that.element.append("<div id='" + wrapperName + "'></div>");
var wrapperElement = that.element.find("#" + wrapperName);
wrapperElement.kendo_MyCustomDialog(options);
},
findDialog: function (dialogId) {
that = this;
var wrapperName = dialogId+"_wrapper";
var dialog = $("#" + wrapperName);
//var dialog = wrapper.find("#" + dialogId);
return dialog.data("kendo_MyCustomDialog");
},
forceCloseAllDialogs: function ()
{
that = this;
$('.MyCustom-window').each(function () {
$(this).data("kendoWindow").close();
});
},
isModalWindowActive: function ()
{
that = this;
return $('.MyCustom-window-modal').length > 0;
},
currentModalWindow: function () {
that = this;
return that.findDialog($('.MyCustom-window-modal')[0].id);
}
});
ui.plugin(MyCustomDialogController);
})(jQuery);
(function ($) {
var kendo = window.kendo,
ui = kendo.ui,
Widget = ui.Widget;
var _MyCustomDialog = Widget.extend({
init: function (element, options) {
var that = this;
Widget.fn.init.call(this, element, options);
that._create();
},
onResize: function () { },
options: {
modal: true,
dialogId: "frmMain",
url: "",
data: null,
pin: false,
width: 300,
height: 300,
actions: ["Close"],
title: "Information",
name: "_MyCustomDialog",
disableMaximize:false,
autosize: false,
onDialogClosed: null,
hideOnClose:false
},
_create: function () {
var that = this;
that.isModalWindowActive = true;
that.modifiedData = false;
that.frmElement = $("#" + that.options.dialogId).data("kendoWindow");
if (that.frmElement == null) {
var template ;
if(that.options.modal)
template = kendo.template(that._templates.divModalFormWrapper);
else
template = kendo.template(that._templates.divFormWrapper);
that.wrapper = $(template(that.options));
that.element.append(that.wrapper);
if (that.options.autosize)
{
that.options.height =null;
that.options.width = null;
}
that.frmElement = that.wrapper.kendoWindow({
title: "Loading...",
modal: that.options.modal,
visible: that.options.autosize,
draggable: true,
resizeable:!that.options.disableMaximize,
width: that.options.width,
height: that.options.height,
resizeable: true,
pinned:that.options.pin,
resize: function () {
that.onResize();
},
content: {
url: that.options.url,
data: that.options.data,
type: "POST",
datatype: "json",
traditional: true
},
refresh: function () {
that.frmElement.title(that.options.title);
if (that.options.autosize) {
that.frmElement.center();
}
},
actions: that.options.actions,
close: function (e) {
that.IsModalWindowActive = false;
if (that.options.hideOnClose == false) {
if (that.frmElement != null)
that.frmElement.destroy();
this.destroy();
that.wrapper.remove("#" + that.options.dialogId);
that.wrapper.empty();
}
if (that.options.onDialogClosed) {
that.options.onDialogClosed(that.modifiedData);
}
}
}).data("kendoWindow");
}
if (that.options.autosize)
that.frmElement.center().open();
else if (that.options.hideOnClose == true)
that.frmElement.open();
else
that.frmElement.center().open();
if (that.options.pin)
that.frmElement.pin();
},
setModifiedFlag:function(modified)
{
var that = this;
that.modifiedData = modified;
},
close: function () {
var that = this;
that.frmElement.close();
},
show: function () {
var that = this;
that.wrapper.show();
that.frmElement.open();
},
setTitle: function (title) {
var that = this;
that.frmElement.title(title);
},
height: function () {
var that = this;
var wtfHeight = that.frmElement.options.height;
if (isNaN(wtfHeight)) {
if (wtfHeight.indexOf("px") >= 0)
wtfHeight = wtfHeight.replace("px", "");
}
return wtfHeight;
},
_templates: {
divModalFormWrapper: "<div id='#=dialogId#' class='MyCustom-window MyCustom-window-modal'></div>",
divFormWrapper: "<div id='#=dialogId#' class='MyCustom-window'></div>"
}
});
// add the widget to the ui namespace so it's available
ui.plugin(_MyCustomDialog);
})(jQuery);
I am using reveal module pattern but can't call the method.
$(function () {
$(document).on("click", '.EditBill', function () {
editModule.EditBill(this);
});
});
var editModule = (function () {
function EditBill(object) {
var itemId = $(object).data('itemid');
loader.show();
$.ajax({
url: 'Bill/Edit',
data: { id: ItemId },
success: function (data) {
loader.hide();
$('#ModelPopup').empty();
$('#ModelPopup').html(data);
$(function () {
$('#editModal').modal();
});
}
});
}
return
{
EditBill: EditBill
}
}());
When I debug in Edge, I click the button ('.EditBill'), the message is
> SCRIPT5007: Unable to get property 'EditBill' of undefined or null
Thanks for Shyju, the answer is return and the first curly brace '{', should be on the same line! It works now. I don't understand why I have to follow this syntas, but it works.
i have a jQUery-confirm and im trying to display some content which have a select and my select.selectMenu() doesn't seem to work because it's being displayed inside the jQUery-confirm. It's just showing the default select.I can easily call .selectMenu() on a select outside the scope and it will change from select to a selectmenu. Example:
HTML:
<div id="aDiv">
<select id="aSelect"> <option value="1"> 1 </option></select>
</div>
<button type="button" id="aButton">Click </button>
CSS:
#aDiv {
display: none;
}
JS:
$(document).ready(function() {
$('#aSelect').selectmenu();
var divVar = $('#aDiv');
$('#aButton').on("click", function() {
$.confirm( {
title: 'Hello',
content: '',
onOpen : function() {
divVar.show();
this.setContent(divVar);
},
onClose : function() {
divVar.hide();
}
});
});
});
How do i make jquery-confirm show jquery ui widgets like selectmenu?
try this, you need to add html markup inside jconfirm and initialize the selectMenu plugin, its better to write the markup inside content instead of defining it outside.
$(document).ready(function() {
// $('#aSelect').selectMenu();
$('#aButton').on("click", function() {
$.confirm( {
title: 'Hello',
content: function(){
return $('#aDiv').html(); // put in the #aSelect html,
},
onContentReady : function() {
this.$content.find('#aSelect').selectMenu(); // initialize the plugin when the model opens.
},
onClose : function() {
}
});
});
});
Please try the following:
You have missed the # for id
$(document).ready(function() {
$('#aSelect').selectMenu();
var divVar = $('#aDiv');
$('#aButton').on("click", function() {
$.confirm( {
title: 'Hello',
content: '',
onOpen : function() {
divVar.show();
this.setContent(divVar);
},
onClose : function() {
divVar.hide();
}
});
});
});
I am writing a script for a project, it has a function to collapse or open the sidebar on click on hamdurger icon but when I click it gives me error
TypeError: this.CollapseSidebar is not a function
The following is my code:
(function($) {
'use strict';
var Prtm = {
Constants: {
LEFTMARGIN:'315px',
COLLAPSELEFTMARGIN: '63px',
},
PrtmEle:{
BODY: $('body'),
SIDEBAR: $('.prtm-sidebar'),
SIDENAV: $('.sidebar-nav'),
MAIN: $('.prtm-main'),
HEADER: $('.prtm-header'),
CONTENTWRAP: $('.prtm-content-wrapper'),
CONTENT: $('.prtm-content'),
PRTMBLOCK: $('.prtm-block'),
FOOTER: $('.prtm-footer'),
HAMBURGER: $('.prtm-bars'),
},
Init:function(){
this.BindEvents();
},
BindEvents:function(){
this.PrtmEle.BODY.on('click',this.PrtmEle.HAMBURGER,function(){
this.CollapseSidebar();
});
},
CollapseSidebar: function(){
this.PrtmEle.HAMBURGER.toggleClass("prtm-sidebar-closed is-active");
this.PrtmEle.BODY.toggleClass("prtm-sidebar-closed is-active");
this.PrtmEle.SIDEBAR.toggleClass('collapse');
},
};
Prtm.Init();
})(jQuery);
When I change this.CollapseSidebar to Prtm.CollapseSidebar it works properly. What I am doing wrong here and how it can be resolved?
Why it do not work? Because a function() binds its own this.
One thing you can do is to use Arrow function which do not bind its own this - like this:
BindEvents:function(){
this.PrtmEle.BODY.on('click',this.PrtmEle.HAMBURGER,() => {
this.CollapseSidebar();
});
}
Inside you click function this will refer to the window - so either you can create a temporary variable like the below or use the arrow function:
BindEvents:function() {
let $this = this;
this.PrtmEle.BODY.on('click',this.PrtmEle.HAMBURGER,function() {
$this.CollapseSidebar();
});
}
I have almost working code, but I can't make autocomplete work in pop-up window.
If I do next thing: when project is running, open Pop-up window and type in FireBug console:
$(":input[data-autocomplete]").each(function() {
$(this).autocomplete({ source: $(this).attr("data-skillsautocomplete") });
});
then everything works perfect.
So, the problem is that I don't know how to pass my jquery function to pop-up window.
Help me with that, please.
JS
ko.bindingHandlers.jqDialog = {
init: function(element, valueAccessor) {
var options = ko.utils.unwrapObservable(valueAccessor()) || {};
ko.utils.domNodeDisposal.addDisposeCallback(element, function() {
$(element).dialog("destroy");
});
setTimeout(function() {
$(element).dialog(options);
}, 0);
}
};
ko.bindingHandlers.openDialog = {
update: function(element, valueAccessor) {
var value = ko.utils.unwrapObservable(valueAccessor());
if (value) {
$(element).dialog("open");
} else {
$(element).dialog("close");
}
}
};
ko.bindingHandlers.jqButton = {
init: function(element, valueAccessor) {
var options = ko.utils.unwrapObservable(valueAccessor()) || {};
//handle disposal
ko.utils.domNodeDisposal.addDisposeCallback(element, function() {
$(element).button("destroy");
});
$(element).button(options);
}
};
$(":input[data-autocomplete]").each(function() {
$(this).autocomplete({ source: $(this).attr("data-skillsAutocomplete") });
});
function pageModel() {
self.selectedVacancyForEdit = ko.observable();
self.skillToAdd = ko.observable();
self.editVacancy = function(){
self.selectedVacancyForEdit(new Vacancy());
//here pop-up window opens
}
self.addSkill = function(){
//adding skill
}
}
UI
....code....
//Pop-up window
<div id="details" data-bind="jqDialog: { autoOpen: false, resizable: true, modal: true, width:'auto'}, template: { name: 'editTmpl', data: selectedVacancyForEdit, if: selectedVacancyForEdit }, openDialog: selectedVacancyForEdit"></div>
<script id="editTmpl" type="text/html">
<fieldset>
<form data-bind="submit: $root.addSkill">
Add skill: <input type="text" data-bind="value: $root.skillToAdd,
valueUpdate: 'blur'"
data-skillsAutocomplete="#Url.Action("SearchSkill", "Home")"
name="search"/>`
</fieldset>
</script>
</div>
try to change
$(":input[data-autocomplete]")
to
$("input[data-autocomplete]")