Kendo Template Invalid in Grid - asp.net-mvc

What am I doing wrong? I get the following error. I am using MVC but not using the MVC wrappers.
Uncaught Error: Invalid template:'
<form action="/Intranet/GalleryFile/Edit" data-ajax="true" data-ajax-method="Post" data-ajax-mode="replace" data-ajax-update="#slideoutmenu" id="form1" method="post"> <input type="hidden" id="fileID" name="fileID" value='#= fileID #' />
<input type="submit" value="Save" class="btn btn-default" />
</form> ' Generated code:'var o,e=kendo.htmlEncode;with(data){o='\n<form action="/Intranet/GalleryFile/Edit" data-ajax="true" data-ajax-method="Post" data-ajax-mode="replace" data-ajax-update="';slideoutmenu" id="form1" method="post"> <input type="hidden" id="fileID" name="fileID" value=';o+='= fileID ';' />
<input type="submit" value="Save" class="btn btn-default" />
</form> ;o+=;}return o;'
JavaScript:
$(document).ready(function () {
var dsGalleryItemFile = new kendo.data.DataSource({
transport: {
read: "#Url.Content("~/Intranet/GalleryItemFile/ListFiles/")#Model.galleryItemID"
},
// determines if changes will be send to the server individually or as batch
batch: false,
schema: {
model: {
id: "fileID",
fields: {
fileID: {
nullable: true
},
filename: {},
fileType: { defaultValue: {fileTypeID: 1, fileType: "Web JPEG"} },
fileType: {},
width: { type: "number" },
height: { type: "number" },
}
}
}
});
$("#gvGalleryItemFile").kendoGrid({
columns: [{
field: "filepath",
title: "File Upload",
width:"250px",//,
//template: "<img src='#=filepath.filepath#' />"
}, {
field: "fileType",
title: "File Type",
template: "#=fileType.fileType#",
}, {
field: "width",
title: "Width(px)",
format: "{0:n0}",
width: "110px"
}, {
field: "height",
title: "Height(px)",
format: "{0:n0}",
width: "110px"
}, {
field: "fileID",
title: "",
template: kendo.template($("#gridEditButtonTemplate").html())
}],
dataSource: dsGalleryItemFile
});
});
Template:
<script type="text/x-kendo-template" id="gridEditButtonTemplate">
#using (Ajax.BeginForm("Edit", "GalleryFile", null, new AjaxOptions { UpdateTargetId = "slideoutmenu", InsertionMode = InsertionMode.Replace, HttpMethod = "Post" }))
{
<input type="hidden" id="fileID" name="fileID" value='#= fileID #' />
<input type="submit" value="Save" class="btn btn-default" />
}
</script>
This isn't even reaching the MVC side of things so I am not including that code. It just won't read the template into my grid column.

The # character has a special meaning in kendo templates and thus it has to be escaped if you want to use it as a regular character.
Your Ajax.BeginForm is creating the attribute
data-ajax-update="#slideoutmenu"
which is what breaks your template. It should be
data-ajax-update="\#slideoutmenu"
I'm not sure if there is a way around this using the Html helpers. The easiest fix would be using plain Html instead.

Related

Knockout-Validation Show Template before input

I have a simple JSFiddle example http://jsfiddle.net/b625zeL5/6/
<script>
ko.validation.init({
registerExtenders: true,
messagesOnModified: true,
insertMessages: false,
parseInputAttributes: true,
messageTemplate: 'errorTemplate',
decorateInputElement: true,
errorElementClass: 'error'
}, true);
var ViewModel = function(){
this.email = ko.observable("")
.extend({ required: true })
.extend({ email: true });
this.password = ko.observable("")
.extend({ required: true });
};
var viewModel = new ViewModel();
viewModel.errors = ko.validation.group(viewModel);
ko.applyBindings(viewModel);
</script>
<form>
<span data-bind="validationMessage: email"></span>
<input type="text" id="email" data-bind="value: email, validationElement: email, valueUpdate:'keyup'" /> <br/>
<span data-bind="validationMessage: password"></span>
<input type="text" id="password" data-bind="value: password, validationElement: password, valueUpdate:'keyup'"/>
</form>
<script type="text/html" id="errorTemplate">
Error: <span data-bind="validationMessage: field">X</span>
</script>
As you can see - I disabled insertMessages because I need error messages to show before input field. Thus I added span with "data-bind="validationMessage: email"" before each text input.
I defined in validation config
messageTemplate: 'errorTemplate'
but error messages still plain text. How can I get messageTemplate to work?
Because you turned off insertMessages, knockout validation won't use your error message template and it will use what you inserted above each field.
You have two options:
For each observable that has a validation, add a custom error message.
Example 1:
this.password = ko.observable("")
.extend({ required: {
params: true,
message: "Error: This is required"
}
});
Change your error template to something like this:
Example 2:
<script type="text/html" id="errorTemplate">
Error: <span data-bind="validationMessage: error_field"></span>
</script>
.. and inside the form, you can call the template like:
<form>
<!-- ko template: { name: 'errorTemplate', data: { error_field: email } }-->
<!-- /ko -->
<input type="text" id="email" data-bind="value: email, validationElement: email, valueUpdate:'keyup'" /> <br/>
...
...
see jsfiddle here with example 2 in action : http://jsfiddle.net/mhgv48e8/
Hope it helps :)

MVC/Razor File Upload View

I self admitted newbie, but I have a view with some code I pasted to provide a file upload. The function works but if the code is in, the "Save" button for the View that was already there stops working. If I had to guess it has something to do with the "HTML.BeginForm" line being there twice.
Here is the top of the view,
#model BrooksSOR.Models.dataOffender
#{
ViewBag.Title = "Edit";
}
<h2>Edit</h2>
<div >
<h2>Upload Files in MVC</h2>
<img src="#Model.Photograph" width="250" height="250" />*
#using (Html.BeginForm("FileUpload", "SOR",
FormMethod.Post, new { enctype = "multipart/form-data" }))
{
<input name="uploadFile" type="file" />
<input type="submit" value="Upload File"/>
<input type="hidden" name="parmPersonID" value="#Model.PersonID" />
}
</div>
#using (Html.BeginForm())
{
#Html.AntiForgeryToken()
#Html.ValidationSummary(true)
<fieldset>
<legend>dataOffender</legend>
<p>
<input type="submit" value="Save" />
<input id="Details" type="button" value="Details" />
</p>
</fieldset>
Remove the #html.BeginForm
The script you would need to send for a file and some other fields with it.
//Purpose: Form Submit: SAVE Client
document.getElementById('frmPage').onsubmit = function (e) {
debugger;
var file = document.getElementById('fileToUpload').files[0];
var filename;
if (file) {
filename = file.name;
}
else {
filename = "";
}
$('#Image').val(filename);
var formObj = $(this);
var formURL = '#Url.Action("SaveMethod", "ControllerName")';
var formData = new FormData(this);
$.ajax({
url: formURL,
type: 'POST',
data: formData,
mimeType: "multipart/form-data",
contentType: false,
cache: false,
processData: false,
success: function (data, textStatus, jqXHR) {
debugger;
alert("Client saved successfully");
},
error: function (jqXHR, textStatus, errorThrown) {
}
});
e.preventDefault(); //Prevent Default action.
}
This is the design:
<div>
<form id="frmPage" class="form-horizontal">
<div class="form-body">
<div class="form-group">
<label id="lblImage" class="col-md-3 control-label">Upload File</label>
<div class="col-md-4">
<input type="file" id="fileToUpload" name="file" />
</div>
</div>
<div class="modal-footer" style="margin-top: 0px">
<div class="pull-right">
<button type="submit" id="btnSave" class="btn blue Save">Save</button>
</div>
</div>
</form>
</div>
Here: The btnSave is submit type, so it will submit that particular form. and form named frmPage will do the jquery script we added.

Knockout checkbox binding, with autoupdate

I am trying to when a person changes the state of previously bound checkbox, I want to update the server with the new value.
So here is what I have:
JSCRIPT
function JobViewModel() {
var self = this;
var baseUri = '/Api/Pedidos/';
self.TotalItems = ko.observable(#Model.TotalItems);
self.AbreviaNome = ko.observable(#Model.AbreviaNome.ToString().ToLower());
self.AbreviaFantasia = ko.observable(#Model.AbreviaFantasia.ToString().ToLower());
self.update = function () {
alert('Boom');
$.ajax({
type: "PUT",
url: baseUri,
data: self.Job,
datatype: "json",
contenttype: "application/json"
})
.done(function (data) {
//handleSuccessFunctionHERE(data);
alert('Magic');
})
.error(function (jqXHR, textStatus, errorThrown) {
alert(errorThrown);
alert("fail");
});
};
}
function JobDetailsViewModel() {
var self = this;
var baseUri = '/Api/Pedidos/';
self.Job = new JobViewModel();
}
HTML
<label class="btn btn-primary" data-bind="css: {active:Job.AbreviaNome }">
<input type="checkbox" data-bind="checked: AbreviaNome , onchange: Job.update" name="type" id="AbreviaNome "> Nome</input>
</label>
This never triggers the update function. I also have tried :
<label class="btn btn-primary" data-bind="css: {active:Job.AbreviaNome }">
<input type="checkbox" data-bind="checked: AbreviaNome , click: Job.update" name="type" id="AbreviaNome "> Nome</input>
</label>
And this within the JobViewModel:
this.AbreviaNome.subscribe(function (newValue) {
alert('test');
}, this);
Any ideas?
You should use subscribe for this and not the onchange handler. You mentioned you tried it, but you subscribed to AbreviaNome instead of AbreviaLogradouro.
Solved the problem, below is the binding:
<label class="btn btn-primary " data-bind="css: {active:Job.AbreviaNome}">
<input type="checkbox" data-bind="checked: Job.AbreviaNome, event: {change: Job.update}" name="type" id="AbreviaNome">Nome/Razão</input>
</label>
Not sure this was the best way but it works.

jquery-ui autocomplete works locally not on heroku

I am using jquery-ui's autocomplete on two input fields of an HTML form in a Sinatra app. They work on my local machine but not on Heroku. Jquery-ui's datepicker works on this same page, so I know the jquery and jquery-ui javascript files are being loaded correctly. Also, I can see that the variable that I am using as the source for the autocomplete is actually getting populated from the database. There are no console errors as well.
Here's the HTML:
<form action="/add-event" method="post">
Date: <input id="datepicker" class="required" type="text" maxlength="50" name="date" /><br />
Headliner: <input id="headliner" class="required" type="text" maxlength="50" name="headliner" /><br />
Venue: <input id="venue" class="required" type="text" maxlength="50" name="venue_name" /><br />
</form>
There are some other fields in the form, but they don't play a part in any of this.
Here's the Jquery:
<script type="text/javascript">
var artist_names = [<%= #artist_names %>];
var venue_names = [<%= #venue_names %>];
$(document).ready(function() {
//Set button disabled
$("input[type=submit]").attr("disabled", "disabled");
var submitForm = function(date, headliner, venue) {
//If form is validated enable form
if ((date != "") && ($.inArray(headliner, artist_names) != -1) && ($.inArray(venue, venue_names) != -1))
{
$("input:submit#event").removeAttr("disabled");
}
else
{
$("input:submit#event").attr("disabled", true);
}
$('#typing').html(date+headliner + venue);
}
$("#datepicker").datepicker({
onSelect: function(dateText, inst) { submitForm(this.value, $('#headliner').val(), $('#venue').val()) }
});
$("#headliner").autocomplete({
source: artist_names,
select: function(event, ui) {
submitForm($('#datepicker').val(), ui.item.value, $('#venue').val());
$('#add-artist').empty();
}
});
$("#venue").autocomplete({
source: venue_names,
select: function(event, ui) {
submitForm($('#datepicker').val(), $('#headliner').val(), ui.item.value);
$('#add-venue').empty();
}
});
//Append a change event listener to you inputs
$('#headliner').keyup(function() {
var val = $('#headliner').val();
if ($.inArray(val, artist_names) == -1)
{
if (val=="")
{
$('#add-artist').empty();
}
else
{
$('#add-artist').html("<strong>" + val + "</strong> isn't in our database. you must first add a profile for them to add this event!<br /><form action='/add-artist-event' method='post'><br />Artist Name: <input type='text' maxlength='50' name='artist_name' value='" + val +"' /><br /> Website: <input type='text' maxlength='50' name='artist_website' /><br /> Facebook: <input type='text' maxlength='50' name='artist_facebook' /><br />Twitter: <input type='text' maxlength='50' name='artist_twitter' /><br />Soundcloud: <input type='text' maxlength='50' name='artist_soundcloud' /><br />Bandcamp: <input type='text' maxlength='50' name='artist_bandcamp' /><br /><button type='button' id='add-artist-button' onclick='addNewArtist();'>Add New Artist!</button></form><br /><br />" );
}
$("input:submit#event").attr("disabled", true);
}
else
{
$('#add-artist').empty();
submitForm($('#datepicker').val(), $('#headliner').val(), $('#venue').val());
}
});
$('#venue').keyup(function() {
var val = $('#venue').val();
if ($.inArray(val, venue_names) == -1)
{
if (val=="")
{
$('#add-venue').empty();
}
else
{
$('#add-venue').html("<strong>" + val + "</strong>" + " is not in our database. you must first add a profile for this venue to add this event!<br /><form action='/add-venue-event' method='post'><br />Venue Name: <input type='text' maxlength='50' name='venue_name' value='" + val +"'/><br />Address: <input type='text' maxlength='50' name='venue_address' /><br />City: <input type='text' maxlength='50' name='venue_city' /><br />State: <input type='text' maxlength='50' name='venue_state' /><br />Zip: <input type='text' maxlength='50' name='venue_zip' /><br />Phone: <input type='text' maxlength='50' name='venue_phone' /><br /> Website: <input type='text' maxlength='50' name='venue_website' /><br /> Facebook: <input type='text' maxlength='50' name='venue_facebook' /><br />Twitter: <input type='text' maxlength='50' name='venue_twitter' /><br /><button type='button' id='add-venue-button' onclick='addNewVenue();'>Add New Venue!</button> </form><br /><br />");
}
$("input:submit#event").attr("disabled", true);
}
else
{
$('#add-venue').empty();
submitForm($('#datepicker').val(), $('#headliner').val(), $('#venue').val());
}
});
});
var addNewArtist = function() {
$.post('/add-event/new-artist', {
artist_name: $(':input[name="artist_name"]').val(),
website: $(':input[name="artist_website"]').val(),
facebook: $(':input[name="artist_facebook"]').val(),
twitter: $(':input[name="artist_twitter"]').val(),
soundcloud: $(':input[name="artist_soundcloud"]').val(),
bandcamp: $(':input[name="artist_bandcamp"]').val()
},
function(output) {
artist_names = output.split(',');
$('#add-artist').html(output);
$('#headliner').autocomplete("option", { source: artist_names });
});
};
var addNewVenue = function() {
$.post('/add-event/new-venue', {
venue_name: $(':input[name="venue_name"]').val(),
street_address: $(':input[name="venue_address"]').val(),
city: $(':input[name="venue_city"]').val(),
state: $(':input[name="venue_state"]').val(),
zip: $(':input[name="venue_zip"]').val(),
phone: $(':input[name="venue_phone"]').val(),
email: $(':input[name="venue_email"]').val(),
website: $(':input[name="venue_website"]').val(),
facebook: $(':input[name="venue_facebook"]').val(),
twitter: $(':input[name="venue_twitter"]').val()
},
function(output) {
venue_names = output.split(',');
$('#add-venue').html(output);
$('#venue').autocomplete("option", { source: venue_names });
});
};
</script>
I was hoping to avoid including all the javascript in the question, but I think it's best that I do. The only other piece is that when I "view source" in chrome I see the two variables are indeed getting populated with data:
var artist_names = [["'Bubonic Bear', "]];
var venue_names = [["'Electric Factory', "]];
UPDATE
If I hardcode a list for the "headliner" field's autocomplete function, the autocomplete works.
$("#headliner").autocomplete({
//source: artist_names,
source: ["band1", "band2", "band3"],
select: function(event, ui) {
submitForm($('#datepicker').val(), ui.item.value, $('#venue').val());
$('#add-artist').empty();
}
});
I'm still not sure of the solution, it seems odd that a variable would be accessible in a local instance of the app and not on heroku. Anyway, I will add more if I figure out more.
I don't see how that would work anywhere. Your data sources:
var artist_names = [<%= #artist_names %>];
var venue_names = [<%= #venue_names %>];
come out as:
var artist_names = [["'Bubonic Bear', "]];
var venue_names = [["'Electric Factory', "]];
and that's not the right format for the jQuery-UI Autocomplete widget. The source option should be a simple array of strings when you're using an inlined source.
You should be inlining your arrays in JSON format:
var artist_names = <%= #artist_names.to_json %>;
var venue_names = <%= #venue_names.to_json %>;
and that should produce things like this:
var artist_names = ["Bubonic Bear"];
var venue_names = ["Electric Factory"];
and the autocomplete widget will be happy with that.
You can play with this demo to see the difference:
http://jsfiddle.net/ambiguous/Brb9p/

How do I postback from a JQuery dialog to another ASP .NET page?

I am using ASP .NET to display a JQuery dialog that has a few input fields. I now need these fields to submitted to an action method like how a normal HTML submit button would work on an ASP .NET MVC application. How do I accomplish this?
This is my form data:
All form fields are required.
<%Html.BeginForm("AddUser", "User"); %>
<fieldset>
<label for="name">Name</label>
<input type="text" name="name" id="name" />
<label for="email">Email</label>
<input type="text" name="email" id="email" value="" />
<label for="password">Password</label>
<input type="password" name="password" id="password" value="" />
</fieldset>
<%Html.EndForm(); %>
"
And this is my script:
$(function() {
$("#dialog").dialog({
bgiframe: true,
height: 400,
width: 600,
modal: true,
buttons: {
'Create user account': function() {
$(this).dialog('close');
},
Cancel: function() {
$(this).dialog('close');
}
}
});
});
Add a line to your code that submits the form:
$(function() {
$("#dialog").dialog({
bgiframe: true,
height: 400,
width: 600,
modal: true,
buttons:
{
'Create user account': function() {
$('#yourDialogFormID').submit(); // add this line
$(this).dialog('close');
},
Cancel: function() {
$(this).dialog('close');
}
}
});
});
You can set the ID by giving the Html.BeginForm() method an argument for htmlAttributes (type object if I remember the structure correctly - look for it in the overload methods in IntelliSense).
You can harvest the data from your form and post it using jQuery.post
$.post("someform.aspx", { name: $("#name").val(), email: $("#email").val() } );

Resources