Kendo UI Core Listview Edit Template with Autocomplete TextBox(Kendo Autocomplete) - asp.net-mvc-5

How to use the Kendo UI Autocomplete textbox inside the Listview Edit Template??While trying to apply the autocomplete option the text box not taking it.The requirement also includes a server side filtering option.This needs to be implemented in an ASP.NET MVC5 Web Application.

I am working on Kendo UI for Jquery and I have implemented something similar. Idea behind the implementation is that you have to add the autocomplete when you are editing the ListView.
I am sharing the "Edit Template" and "ListView JS" below.
I found the idea here http://jsfiddle.net/F4NvL/
<script type="text/x-kendo-tmpl" id="editTemplate">
<div class="product-view k-widget">
<dl>
<dt>Product Name</dt>
<dd>
<label for="PAPC">Project Code<span class="k-icon k-i-star requiredstar" data-toggle="tooltip" title="Required"></span></label>
<input type="text" required name="PAPC" validationMessage="Hotel is required" data-bind="value: ProjectCode" />
<span class="k-invalid-msg" data-for="PAPC"></span>
</dd>
</dl>
<div class="edit-buttons">
<a class="k-button k-update-button" href="\\#"><span class="k-icon k-i-check"></span></a>
<a class="k-button k-cancel-button" href="\\#"><span class="k-icon k-i-cancel"></span></a>
</div>
</div>
var listView = $("#lvPA").kendoListView({
dataSource: datasrc,
template: kendo.template($("#template").html()),
editTemplate: kendo.template($("#editTemplate").html()),
edit: function (e) {
var model = e.model;
var item = $(e.item[0]);
var projectcode = item.find('[name="PAPC"]'); //Get your element
//Add a autocomplete here
projectcode.kendoAutoComplete({
valueTemplate: '<span>#:data.ProjectCode#</span>',
template: projectTemplate,
minLength: 3,
autoWidth: true,
dataTextField: "ProjectCode",
dataSource: new kendo.data.DataSource({
type: "GET",
serverFiltering: true,
transport: {
read: ProjectAPI,
parameterMap: function (data, type) {
return { filter: $('[name="PAPC"]').val() };
}
},
}),
height: 200
});
}
}).data("kendoListView");

Related

Angularjs Material md-datepicker within Formly template will not open calendar pane

I'm trying to create a Formly template using md-datepicker. Unfortunately, when I click on the md-datepicker control within my form the calendar panel does not open.
controller code:
{
className: 'col-xs-6',
key: 'dateCreated',
type: 'materialdatepicker',
templateOptions: {
label: 'Created'
},
expressionProperties: {
'templateOptions.disabled': function () {
return !vm.options.editMode;
},
'templateOptions.required': function () {
return vm.options.editMode;
}
}
}
template:
<script type="text/ng-template" id="materialdatepicker.html">
<div layout="column">
<div flex="100">
<p class="input-group" style="display: block; margin: 0px;">
<md-datepicker id="{{::id}}" name="{{::id}}" ng-model="model[options.key]"></md-datepicker>
</p>
<div class="formlyMessages" ng-messages="fc.$error" ng-if="fc.$touched">
<div class="formlyMessage" ng-message="{{::name}}" ng-repeat="(name, message) in ::options.validation.messages">
{{message(fc.$viewValue, fc.$modelValue, this)}}
</div>
</div>
</div>
</div>
</script>
formly config:
formlyConfigProvider.setType({
name: 'materialdatepicker',
templateUrl: 'materialdatepicker.html',
wrapper: ['bootstrapLabel', 'bootstrapHasError'],
defaultOptions: {
ngModelAttrs: ngModelAttrs
},
controller: ['$scope', function ($scope) {
$scope.materialdatepicker = {};
}]
});
I can't seem to figure out how to get the calendar panel to open. I'm not getting any errors in the console and the control does get populated with my initial value.
Any ideas?
What I forgot to mention in my original post was that this form is contained within a modal window ($uibModal). As such, the calendar pane was popping up behind my modal window.
The solution found here worked for me: Angular Material DatePicker Calendar Shows Behind Angular Modal
You need to tell your calendar pane to open with a high z-index so it renders above the modal. Place this style sheet code into your modal html:
<style>
.md-datepicker-calendar-pane {
z-index: 1200;
}
</style>

Knockout two way binding not working with Sharepoint modal dialog

I'm trying two way binding (knockout observables) with sharepoint modal dialog
var ViewModel = function () {
var self = this;
self.firstName = "Irfanullah";
self.lastName = ko.observable('M.');
self.fullName = ko.computed(function () {
return self.firstName + ' ' + self.lastName();
});
};
ko.applyBindings(new ViewModel());
<button type=button onclick="openDialog2()">click me</button>
<div id="wrap" style="display:none">
<div id="d10" class="dialogHolder">
<div id="kobasic">
<h4>Editable data</h4>
<p><input type="text" data-bind="value: firstName" /></p>
<p><input type="text" data-bind="value: lastName" /></p>
<p>Full Name: <span data-bind="text: fullName"></span></p>
</div>
</div>
When i test this code on sharepoint wiki page its working good, but when i use same code on sharepoint dialog it shows values (one way binding)but two way binding/ko.observable() does not work (when i type something in lastname text box it does not update fullname)
function openDialog2() {
var e = document.getElementById('d10');
var options = {
title: "Test Knockout",
width: 700,
height: 800,
html: e.cloneNode(true)
};
mydialog = SP.UI.ModalDialog.showModalDialog(options);
}
I believe that is alll becase e.cloneNode(true) but i could not figureout alternat solution
For SharePoint dialogs I am using this approach:
(note: jQuery needed)
// create dom element
var element = document.createElement('div');
// apply my custom view
$(element).append('<!--my HTML -->');
// apply knockout bindings
ko.applyBindings(myViewModel, element);
// show sharepoint modal dialog
var options = {
allowMaximize: false,
html: element,
title: "My title",
autoSize: true,
showClose: true,
dialogReturnValueCallback: myCallback
};
SP.UI.ModalDialog.showModalDialog(options);
So in your case:
var element = document.createElement('div');
$(element).append('<div id="d10" class="dialogHolder"><div id="kobasic"><h4>Editable data</h4><p><input type="text" data-bind="value: firstName" /></p><p><input type="text" data-bind="value: lastName" /></p><p>Full Name: <span data-bind="text: fullName"></span></p></div></div>');
ko.applyBindings(new ViewModel(), element);
var options = {
allowMaximize: false,
html: element,
title: "My title",
autoSize: true,
showClose: true,
dialogReturnValueCallback: myCallback
};
SP.UI.ModalDialog.showModalDialog(options);

Nested ListView or Nested Repeater

I am trying to created a nested repeater or a nested list view using WinJS 4.0, but I am unable to figure out how to bind the data source of the inner listview/repeater.
Here is a sample of what I am trying to do (note that the control could be Repeater, which I would prefer):
HTML:
<div id="myList" data-win-control="WinJS.UI.ListView">
<span data-win-bind="innerText: title"></span>
<div data-win-control="WinJS.UI.ListView">
<span data-win-bind="innerText: name"></span>
</div>
</div>
JS:
var myList = element.querySelector('#myList).winControl;
var myData = [
{
title: "line 1",
items: [
{name: "item 1.1"},
{name: "item 1.2"}
]
},
{
title: "line 2",
items: [
{name: "item 2.1"},
{name: "item 2.2"}
]
}
];
myList.data = new WinJS.Binding.List(myData);
When I try this, nothing renders for the inner list. I have attempted trying to use this answer Nested Repeaters Using Table Tags and this one WinJS: Nested ListViews but I still seem to have the same problem and was hoping it was a little less complicated (like KnockOut).
I know it is mentioned that WinJS doesn't support nested ListViews, but that seems to be a few years ago and I am hoping that is still not the issue.
Update
I was able to get the nested repeater to work correctly, thanks to Kraig's answer. Here is what my code looks like:
HTML:
<div id="myTemplate" data-win-control="WinJS.Binding.Template">
<div
<span>Bucket:</span><span data-win-bind="innerText: name"></span>
<span>Amount:</span><input type="text" data-win-bind="value: amount" />
<button class="removeBucket">X</button>
<div id="bucketItems" data-win-control="WinJS.UI.Repeater"
data-win-options="{template: select('#myTemplate')}"
data-win-bind="winControl.data: lineItems">
</div>
</div>
</div>
<div id="budgetBuckets" data-win-control="WinJS.UI.Repeater"
data-win-options="{data: Data.buckets,template: select('#myTemplate')}">
</div>
JS: (after the "use strict" statement)
WinJS.Namespace.define("Data", {
buckets: new WinJS.Binding.List([
{
name: "A",
amount: 5,
lineItems: new WinJS.Binding.List( [
{ name: 'test item1', amount: 50 },
{ name: 'test item2', amount: 25 }
]
)
}
])
})
*Note that this answers part of my question, however, I would really like to do this all after a repo call and set the repeater data source programmatically. I am going to keep working towards that and if I get it I will post that as the accepted answer.
The HTML Repeater control sample for Windows 8.1 has an example in scenario 6 with a nested Repeater, and in this case the Repeater is created through a Template control. That's a good place to start. (I discuss this sample in Chapter 7 of Programming Windows Store Apps with HTML, CSS, and JavaScript, 2nd Edition, starting on page 372, or 374 for the nested part.)
Should still work with WinJS 4, though I haven't tried it.
Ok, so I have to give much credit to Kraig because he got me on the correct path to getting this worked out and the referenced book Programming Windows Store Apps with HTML, CSS, and JavaScript, 2nd Edition is amazing.
The original issue was a combination of not using templates correctly (using curly braces in the data-win-bind attribute), not structuring my HTML correctly and not setting the child lists as WinJS.Binding.List data source. Below is the final working code structure to created a nested repeater when binding the data from code only:
HTML:
This is the template for the child lists. It looks similar, but I plan on add more things so I wanted it separate instead of recursive as referenced in the book. Note that the inner div after the template control declaration was important for me.
<div id="bucketItemTemplate" data-win-control="WinJS.Binding.Template">
<div>
<span>Description:</span>
<span data-win-bind="innerText: description"></span>
<span>Amount:</span>
<input type="text" data-win-bind="value: amount" />
<button class="removeBucketItem">X</button>
</div>
</div>
This is the main repeater template for the lists. Note that the inner div after the template control declaration was important for me. Another key point was using the "winControl.data" property against the property name of the child lists.
<div id="bucketTemplate" data-win-control="WinJS.Binding.Template">
<div>
<span>Bucket:</span>
<span data-win-bind="innerText: bucket"></span>
<span>Amount:</span>
<input type="text" data-win-bind="value: amount" />
<button class="removeBucket">X</button>
<div id="bucketItems" data-win-control="WinJS.UI.Repeater"
data-win-options="{template: select('#bucketItemTemplate')}"
data-win-bind="winControl.data: lineItems">
</div>
</div>
</div>
This is the main control element for the nested repeater and it is pretty basic.
<div id="budgetBuckets" data-win-control="WinJS.UI.Repeater"
data-win-options="{template: select('#bucketTemplate')}">
</div>
JavaScript:
The JavaScript came down to a few simple steps:
Getting the winControl
var bucketsControl = element.querySelector('#budgetBuckets').winControl;
Looping through the elements and making the child lists into Binding Lists - the data here is made up but could have easily came from the repo:
var bucketsData = selectedBudget.buckets;
for (var i = 0; i < bucketsData.length; i++) {
bucketsData[i].lineItems =
new WinJS.Binding.List([{ description: i, amount: i * 10 }]);
}
Then finally converting the entire data into a Binding list and setting it to the "data" property of the winControl.
bucketsControl.data = new WinJS.Binding.List(bucketsData);
*Note that this is the entire JavaScript file, for clarity.
(function () {
"use strict";
var nav = WinJS.Navigation;
WinJS.UI.Pages.define("/pages/budget/budget.html", {
// This function is called whenever a user navigates to this page. It
// populates the page elements with the app's data.
ready: function (element, options) {
// TODO: Initialize the page here.
var bindableBuckets;
require(['repository'], function (repo) {
//we can setup our save button here
var appBar = document.getElementById('appBarBudget').winControl;
appBar.getCommandById('cmdSave').addEventListener('click', function () {
//do save work
}, false);
repo.getBudgets(nav.state.budgetSelectedIndex).done(function (selectedBudget) {
var budgetContainer = element.querySelector('#budgetContainer');
WinJS.Binding.processAll(budgetContainer, selectedBudget);
var bucketsControl = element.querySelector('#budgetBuckets').winControl;
var bucketsData = selectedBudget.buckets;
for (var i = 0; i < bucketsData.length; i++)
{
bucketsData[i].lineItems = new WinJS.Binding.List([{ description: i, amount: i * 10 }]);
}
bucketsControl.data = new WinJS.Binding.List(bucketsData);
});
});
WinJS.UI.processAll();
}
});
})();

Unobtrusive validation with Jquery Steps Wizard

Recently I asked a question for how to customize the JQuery Steps as I wanted to use partial views instead of static content. I have partially solved that problem by using the following code supported by jquery-steps,
<h3>Step 1</h3>
<section data-mode="async" data-url="/Formation/RenderStep1"></section>
<h3>Step 2</h3>
<section data-mode="async" data-url="/Formation/RenderStep2"></section>
Now the big problem I am facing right now is how to use unobtrusive validation. I don't want to use JQuery custom validation and there must be some way of using Obtrusive with it.
Each partial view that is rendered has its own form. I want to validate the form in the onStepChanging function of jquery-steps,
$("#my-steps").steps({
headerTag: "h3",
bodyTag: "section",
contentMode: "async",
transitionEffect: "fade",
stepsOrientation: "vertical",
onStepChanging: function (event, currentIndex, newIndex) {
return true;
}
});
I have tried calling $.validator.unobtrusvie.parse('#myform'); in the onStepChanging function but ('#myform') is undefined and still I don't know that whether this is the right way to call the unobtrusive validation manually. Kindly guide me and show me the direction to achieve this. Any help will be highly appreciated.
It sounds like your trying manage multiple forms within the JQuery Steps library and I don't think that is what its intended for.
When you configure JQuery Steps, you set it up against the form in your view.
Unobtrusive JQuery Validation is looking at the model in your view and automatically configuring the HTML with the relevant data attributes for error handling.
This validation should be firing at the client side automatically.
There shouldn't be a problem with using Partial View's, as long as there encapsulated within the same form element.
What is the requirement to have each partial view wrapped in its own form? If your trying to make multiple posts throughout the JQuery Steps form wizard, your defeating the object.
At each step in the JQuery Steps form, your only validating the one form like this :-
onStepChanging: function (event, currentIndex, newIndex) {
//Allways allow user to move backwards.
if (currentIndex > newIndex) {
return true;
}
// Remove the validation errors from the next step, incase user has previously visited it.
var form = $(this);
if (currentIndex < newIndex) {
// remove error styles
$(".body:eq(" + newIndex + ") label.error", form).remove();
$(".body:eq(" + newIndex + ") .error", form).removeClass("error");
}
//disable validation on fields that are disabled or hidden.
form.validate().settings.ignore = ":disabled,:hidden";
return form.valid();
}
Once the user has finished entering data, and the client side validation has been met, you hook into the onFinished method and post the form :-
onFinished: function (event, currentIndex) {
var form = $(this);
form.submit();
}
The purpose of JQuery Steps is to allow the user to have a fluid experience of filling out a form and to not be overwhelmed with the number of questions been asked.
From the developers perspective, it enables us to split up the form into nice size-able chunks without having to worry about saving progress between screens or losing the state of the form data and allows us to capture all of the required data with only having to make that one post once all validation criteria has been met.
I tried the formvalidation plugin, it will relax your mind from searching in validation without form tag or validation without submit the form that's the issue I solved when I tried it.
I know it's not free but you can try it from here, personally I like it
First update height after validation
<style type="text/css">
/* Adjust the height of section */
#profileForm .content {
min-height: 100px;
}
#profileForm .content > .body {
width: 100%;
height: auto;
padding: 15px;
position: relative;
}
Second, add data-steps index to your section*
<form id="profileForm" method="post" class="form-horizontal">
<h2>Account</h2>
<section data-step="0">
<div class="form-group">
<label class="col-xs-3 control-label">Username</label>
<div class="col-xs-5">
<input type="text" class="form-control" name="username" />
</div>
</div>
<div class="form-group">
<label class="col-xs-3 control-label">Email</label>
<div class="col-xs-5">
<input type="text" class="form-control" name="email" />
</div>
</div>
<div class="form-group">
<label class="col-xs-3 control-label">Password</label>
<div class="col-xs-5">
<input type="password" class="form-control" name="password" />
</div>
</div>
<div class="form-group">
<label class="col-xs-3 control-label">Retype password</label>
<div class="col-xs-5">
<input type="password" class="form-control" name="confirmPassword" />
</div>
</div>
</section>
Third, javascript code
<script>
## // to adjust step height to fit frame after showing validation messages##
$(document).ready(function() {
function adjustIframeHeight() {
var $body = $('body'),
$iframe = $body.data('iframe.fv');
if ($iframe) {
// Adjust the height of iframe
$iframe.height($body.height());
}
}
// IMPORTANT: You must call .steps() before calling .formValidation()
$('#profileForm')
// setps setup
.steps({
headerTag: 'h2',
bodyTag: 'section',
onStepChanged: function(e, currentIndex, priorIndex) {
// You don't need to care about it
// It is for the specific demo
adjustIframeHeight();
},
// Triggered when clicking the Previous/Next buttons
// to apply validation to your section
onStepChanging: function(e, currentIndex, newIndex) {
var fv = $('#profileForm').data('formValidation'), // FormValidation instance
// The current step container
$container = $('#profileForm').find('section[data-step="' + currentIndex +'"]');
// Validate the container
fv.validateContainer($container);
var isValidStep = fv.isValidContainer($container);
if (isValidStep === false || isValidStep === null) {
// Do not jump to the next step
return false;
}
return true;
},
// Triggered when clicking the Finish button
onFinishing: function(e, currentIndex) {
var fv = $('#profileForm').data('formValidation'),
$container = $('#profileForm').find('section[data-step="' + currentIndex +'"]');
// Validate the last step container
fv.validateContainer($container);
var isValidStep = fv.isValidContainer($container);
if (isValidStep === false || isValidStep === null) {
return false;
}
return true;
},
onFinished: function(e, currentIndex) {
// Uncomment the following line to submit the form using the defaultSubmit() method
// $('#profileForm').formValidation('defaultSubmit');
// For testing purpose
$('#welcomeModal').modal();
}
})
.formValidation({
framework: 'bootstrap',
icon: {
valid: 'glyphicon glyphicon-ok',
invalid: 'glyphicon glyphicon-remove',
validating: 'glyphicon glyphicon-refresh'
},
// This option will not ignore invisible fields which belong to inactive panels
excluded: ':disabled',
fields: {
username: {
validators: {
notEmpty: {
// for asp.net i used element attribute to integerated with unobtrusive validation
// message :$('username').attr('data-val-required')
message: 'The username is required'
},
stringLength: {
min: 6,
max: 30,
message: 'The username must be more than 6 and less than 30 characters long'
},
regexp: {
regexp: /^[a-zA-Z0-9_\.]+$/,
message: 'The username can only consist of alphabetical, number, dot and underscore'
}
}
},
email: {
validators: {
notEmpty: {
message: 'The email address is required'
},
emailAddress: {
message: 'The input is not a valid email address'
}
}
},
password: {
validators: {
notEmpty: {
message: 'The password is required'
},
different: {
field: 'username',
message: 'The password cannot be the same as username'
}
}
},
confirmPassword: {
validators: {
notEmpty: {
message: 'The confirm password is required'
},
identical: {
field: 'password',
message: 'The confirm password must be the same as original one'
}
}
}
}
});

Date is not showing up properly in Liferay portlet

In my portlet I have one form where I am showing dates through following code
JSP:
<aui:input type="text" name="createdDate" size="10" value="" id="createdDate" label="" />
<div class="calendar-icon" id="imageDiv">
<span class="aui-icon aui-icon-calendar"></span>
</div>
Script in JSP
renderCalendar('#imageDiv','#<portlet:namespace/>createdDate','#calendarDiv');
function renderCalendar(imageDiv,inputDisplay,calendarDiv) {
AUI().ready('aui-calendar', function(A) {
var inputField1 = A.one(imageDiv);
var inputField2 = A.one(inputDisplay);
var calendar1 = new A.Calendar({
dates: [ new Date() ],
dateFormat: '%d/%m/%Y',
selectMultipleDates: false,
after: {
datesChange: function(event) {
var formatted = event.target.getFormattedSelectedDates();
inputField2.val(formatted);
calendar1.toggle(); // hide after a date was selected
}
}
}).render(calendarDiv);
var boundingBoxCal1 = calendar1.get('boundingBox');
boundingBoxCal1.setX(inputField1.getX());
boundingBoxCal1.setY(inputField1.getY() + 25);
calendar1.hide();
inputField1.on('click', function() { calendar1.toggle(); });
});
}
It is showing date on page but the problem is with layout Date text field and calender icon both not coming in same line.Please help me out
use <span> instead of <div>. <div> opens a new block while <span> will remain in the same line
Strange that <span> didn't fix your problem. Try floating your <div> to the left, as in,
<div class="calendar-icon" id="imageDiv" style="float: left;">

Resources