I have an asp.net MVC app. One of the forms posts json data to a public method (not an action, perhaps it will be later) on the controller. This works great in IE 8. However, it does not work in Firefox 3.5.
The view is a list of jquery sortable objects inside of a form. Here is a stripped down version of the form:
<form class="cmxform" id="UserForm" method="post" action="/Home/Index">
//...the <li> objects that are sortable
<input type="submit" value="Save Changes" onclick="SaveLinks();" />
</form>
Here is the javascript to fire when the button is clicked. /Home/ProcessLinks is a public method in the controller, and Visible and Invisible is a parameter being passed to the method:
function SaveLinks() {
var VisibleList = document.getElementById('sortable1');
var InvsibleList = document.getElementById('sortable2');
for (var i = 0; i < VisibleList.childNodes.length; i++) {
var link = {};
link.id = VisibleList.childNodes[i].childNodes[1].innerText;
link.title = VisibleList.childNodes[i].childNodes[2].innerText;
link.description = VisibleList.childNodes[i].childNodes[3].innerText;
link.url = VisibleList.childNodes[i].childNodes[4].innerText;
link.order = i + 1;
$.post("/Home/ProcessLinks/Visible", $.toJSON(link), function(data, testStatus) {
/*This is where the user can be notified that the item was saved successfully*/
//alert(link.id + " has been updated");
window.location.reload();
}, "text");
}
for (var i = 0; i < InvsibleList.childNodes.length; i++) {
var link = {};
link.id = InvsibleList.childNodes[i].childNodes[1].innerText;
link.title = InvsibleList.childNodes[i].childNodes[2].innerText;
link.description = InvsibleList.childNodes[i].childNodes[3].innerText;
link.url = InvsibleList.childNodes[i].childNodes[4].innerText;
link.order = i + 1;
$.post("/Home/ProcessLinks/Invisible", $.toJSON(link), function(data, testStatus) {
/*This is where the user can be notified that the item was saved successfully*/
//alert(link.id + " has been updated");
window.location.reload();
}, "text");
}
}
It is my belief that the above method does not get triggered when in Firefox, as the breakpoints I place with Firebug don't get hit.
For fun, here is my serverside function:
public string ProcessLinks(string id)
{
string Type = id;
string json = Request.Form[0];
var serializer = new DataContractJsonSerializer(typeof(JsonObject));
var memoryStream = new MemoryStream(Encoding.Unicode.GetBytes(json));
JsonObject item = (JsonObject)serializer.ReadObject(memoryStream);
memoryStream.Close();
return "hello";
}
And my custom class JsonObject:
[DataContract]
public class JsonObject
{
[DataMember]
internal int id { get; set; }
[DataMember]
internal string title { get; set; }
[DataMember]
internal string description { get; set; }
[DataMember]
internal string order { get; set; }
[DataMember]
internal string url { get; set; }
}
Do you have any idea what I'm doing wrong? I can't seem to nail it down.
Firefox does not support innerText. Use innerHTML instead.
Another possible reason is the following HTML:
<div>
<span>foo</span>
<span>bar</span>
</div>
will have the following structure in IE
div
|---span(childNode[0])
| |
| '---text---foo
|
'---span(childNode[1])
|
'---text---bar
while in all other browsers including firefox it will have the following structure:
div
|---text(childNode[0])---newline and tabs
|
|---span(childNode[1])
| |
| '---text---foo
|
|---text(childNode[2])---newline and tabs
|
'---span(childNode[3])
|
'---text---bar
This ridiculous behavior is mandated by the W3C spec. So IE is technically wrong here.
Now, I notice in your code you make assumptions about childNode indexing without checking element.nodeName. That could be where the problem lies.
Update:
after looking at the code you uploaded I removed the <input type="submit... button from the form and added a button tag outside the form like this:
</form>
<button onclick="SaveLinks();">Save Changes</button>
After click this I got an error in FireFox:
"VisibleList.childNodes[i].childNodes[1] is undefined"
To correct this I took the code from jerjer's answer ( i had to modify it a bit ) and came up with the following SaveLinks() method that works in FF.
function SaveLinks() {
$('#sortable1 li').each(function(i, item) {
var divs = $('div:not(.imagecontainer)', this);
var link = {
id: $(divs[0]).text(),
title: $(divs[1]).text(),
description: $(divs[2]).text(),
url: $(divs[3]).text(),
order: i + 1
};
$.post("/Home/ProcessLinks/Visible", $.toJSON(link), function(data, testStatus) {
/*This is where the user can be notified that the item was saved successfully*/
alert(link.id + " has been updated");
//window.location.reload();
}, "text");
});
$('#sortable2 li').each(function(i, item) {
var divs = $('div:not(.imagecontainer)', this);
var link = {
id: $(divs[0]).text(),
title: $(divs[1]).text(),
description: $(divs[2]).text(),
url: $(divs[3]).text(),
order: i + 1
};
$.post("/Home/ProcessLinks/Invisible", $.toJSON(link), function(data, testStatus) {
/*This is where the user can be notified that the item was saved successfully*/
alert(link.id + " has been updated");
//window.location.reload();
}, "text");
});
return false;
}
Since you are using jquery, you might as well use the jquery's shorthand for getting/setting text/html.
for instance getting text content:
link.id = $(VisibleList.childNodes[i].childNodes[1]).text();
link.title = $(VisibleList.childNodes[i].childNodes[2]).text();
link.description = $(VisibleList.childNodes[i].childNodes[3]).text();
link.url = $(VisibleList.childNodes[i].childNodes[4]).text();
link.order = i + 1;
getting html content:
link.id = $(VisibleList.childNodes[i].childNodes[1]).html();
link.title = $(VisibleList.childNodes[i].childNodes[2]).html();
link.description = $(VisibleList.childNodes[i].childNodes[3]).html();
link.url = $(VisibleList.childNodes[i].childNodes[4]).html();
link.order = i + 1;
This is the jquery equivalent:
$('#sortable1 li').each(function(){
var $li = $(this);
var link = {};
link.id = $li.children(1).text();
link.title =$li.children(2).text();
link.description = $li.children(3).text();
link.url = $li.children(4).text();
link.order = i + 1;
$.post("/Home/ProcessLinks/Visible", $.toJSON(link), function(data, testStatus) {
/*This is where the user can be notified that the item was saved successfully*/
//alert(link.id + " has been updated");
window.location.reload();
}, "text");
});
Related
previous quest
i make tree view in razor page
As I tried to call multiple tree views simultaneously in cshtml, I ended up using a recursive function.
program sequence
Get all tree data from DB
Bind tree data to TreeNode
Display in html using recursive function
So while I was looking for it, I found something that can make html directly in the back and I'm going to use it.
When creating jsonresult, "There was a case where the js function itself was not recognized due to a problem.
I want to know if there is a way
Questions
Is the way I'm building my tree a very strange way now?
public class TreeNode
{
public List<TreeNode> subTreeNodes { get; set; }
public string dataName { get; set; }
public bool deployment { get; set; }
public string board_id { get; set; }
public TreeNode(string dName)
{
dataName = dName;
deployment = false;
}
}
cshtml.cs
public IActionResult OnGet()
{
//if(session)
List<TreeNode> treeData;
IQueryable<tbl_tree> iqueryTree;
iqueryTree = _context.tbl_tree.Where(x => x.upcode == "AAAAAA");
var datas = iqueryTree.ToList();
tree_List = new List<TreeNode>();
for (int i = 0; i < datas.Count; i++)
{
TreeNode treeNode = new TreeNode(datas[i].name);
treeNode.subTreeNodes = ConstructorData(datas[i].icd11);
treeNode.board_id = datas[i].icd11;
tree_List.Add(treeNode);
}
TempData.Set("TreeData", tree_List);
jsonData = UpdateRecursiveData(tree_List[1]);
return Page();
}
public List<TreeNode> ConstructorData(string str)
{
List<TreeNode> treeNodes = new List<TreeNode>();
IQueryable<tbl_tree> iqueryTree;
iqueryTree = _context.tbl_tree.Where(x => x.upcode == str);
var datas = iqueryTree.ToList();
for (int i = 0; i < datas.Count; i++)
{
TreeNode treeNode = new TreeNode(datas[i].name);
treeNode.board_id = datas[i].icd11;
treeNode.subTreeNodes = ConstructorData(datas[i].icd11);
treeNodes.Add(treeNode);
}
return treeNodes;
}
How will you package "in jsonresult?"
JsonResult UpdateRecursiveData(TreeNode tn)
{
JsonResult jsonResult = new JsonResult(
"<input type = 'checkbox' onclick = requestMyAction( '" +tn.board_id+"', this.checked, 'loader-"+tn.dataName+"');' />" +
"<div class='loader' style='display: none;' id='loader-'" +tn.dataName+ "'> "+tn.dataName+ "</div>" +
"<br />");
//if (tn.deployment)
//{
//for (int i = 0; i<tn.subTreeNodes.Count; i++)
// UpdateRecursiveData(tn.subTreeNodes[i]);
//}
return jsonResult;
}
this cshtml
<input type="checkbox"
onclick="requestMyAction('#Model.tree_List[0].board_id', this.checked,
'loader-#Model.tree_List[0].dataName');" />
<div class="loader" style="display: none;" id="loader-#Model.tree_List[0].dataName">
#Model.tree_List[0]
</div>
<div id="data">
#Html.Raw(Model.jsonData.Value)
</div>
remove all
this error is syntax error js complier is not working in VS studio
string strResult =
"<div style='padding: 0 0 0 10px ;display:"+defaultView+"'id='"+tn.dataName+tn.upCode+"'>" +
"<input type='checkbox'style='visibility:"+subCheck+";'onclick=requestMyAction('"+tn.icd11+"',this.checked,'"+tn.dataName+tn.upCode+"');>" +
"<span onclick = 'CallViewBorad("+tn.board_Id + ")' >"+tn.dataName+" </span>";
I'm using asp.net mvc razor, and I'm making a view to create a parent's object, but along creating the parent I need to create 'n' child objects. How can I do this exactly?
I will reinforce that I'm not expecting to display the object's, I need to create them in one go, I say this only because I saw too many misunderstanding in my research.
Let me explain exactly what i need to do:
I have a model called 'Car', this model have a child element: ICollection< Extra >, when the user will insert a new 'Car' he may be capable of insert 'Extra' stuff before inserting the 'Car' to the database. And the 'Extra' could have N elements, so it's not fixed.
My model as example:
[Table("Car")]
public partial class Car
{
[Key]
public int IdCar { get; set; }
[Required]
[StringLength(10)]
[Display(Name = "Car")]
public string DsCar { get; set; }
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
public virtual ICollection<Extra> Extra{ get; set; }
}
Here's a view example of what i want to do that could help:
Insert Page
I wish to avoid the page refreshing effect if possible too.
After some researching I did not find anything suitable for my case, so I ended doing some code by myself.
(I was not able to search to much, I believe there must be a better answer somewhere)
As I want to make them reusable i created them in a partial view.
<div class="form-group">
#{
TempData["ParentToken"] = ViewBag.Token;
Html.RenderAction("EstoqueOpcional", "Estoques");
}
</div>
In my partial view I created an AjaxForms:
#using (Ajax.BeginForm("EstoqueOpcionalCreate", new AjaxOptions() { OnSuccess = "RegistroAdicionadoOpcional()", OnFailure = "ConectionFailed()", HttpMethod = "Post" })){
#Html.Hidden("PageToken", (object)TempData["ParentToken"])
<!-- MY FIELDS -->
<input type="submit" value="Atualizar" class="btn btn-save" />
...
I have a page token in every page so I can create TempDatas using them without problem of the user opening multiple tabs of the same view. (ViewBag's isn't available because I'm not able to send anything back to the page).
Those are the scripts I created to control the display and stuff. (Most of them are still strongly typed as I still not refined my code yet)
<script>
function RegistroAdicionadoOpcional() {
var newData = $("#dsopcional").val();
var pass = true;
$("#tableEstoqueOpcional .CheckData").each(function () {
if ($(this).html() == newData)
pass = false;
});
if (pass) {
$("#tableEstoqueOpcional").append("<tr><td class=\"CheckData\">" + newData + "</td>" +
"<td class=\"grid-cell temp-cell\" style=\"padding: 0px !important;\">" + "Remover" + "</td></tr>");
$("#dsopcional").val("");
$("#dsopcional").focus();
}
else {
Message("Error", "Esse valor já foi inserido.");
$("#dsopcional").focus();
}
}
function RemoveDataOpcional(value) {
$.ajax({
url: "/Estoques/RemoverOpcional",
data: { opcional: value, PageToken: $("#PageToken").val() },
cache: false,
type: "POST",
timeout: 5000,
success: function (data) {
if (data == "True") {
$("#tableEstoqueOpcional .CheckData").each(function () {
if ($(this).html() == value)
$(this).parent('tr').remove();
});
}
else
Message("Error", "Não foi possível remover o valor escolhido, tente atualizar a página.");
},
error: function (reponse) {
Message("Error", "Não foi possível remover o valor selecionado, se o erro persistir tente recarregar a página.");
}
});
}
#{
var regs = "";
if (TempData["EstoqueOpcional"] != null)
{
foreach (var item in (List<Models.EstoqueOpcional>)TempData["EstoqueOpcional"])
{
regs += "<tr><td class=\\\"CheckData\\\">" + item.DsOpcional + "</td>" +
"<td class=\\\"grid-cell temp-cell\\\" style=\\\"padding: 0px !important;\\\">" + "Remover" + "</td></tr>";
}
}
TempData["DisplayEstoque"] = regs;
}
$(document).ready(function () {
var text = "#Html.Raw(HttpUtility.HtmlDecode(TempData["DisplayEstoque"].ToString()))";
$("#tableEstoqueOpcional").append(text);
});
In my controller I created those methods to control the values in the TempData:
public ActionResult EstoqueOpcional()
{
return PartialView(new EstoqueOpcional());
}
[HttpPost]
public bool EstoqueOpcionalCreate(EstoqueOpcional estoqueOpcional, string PageToken)
{
List<EstoqueOpcional> estoqueOpcionals = new List<EstoqueOpcional>();
if (TempData["EstoqueOpcional" + PageToken] != null)
estoqueOpcionals.AddRange((List<EstoqueOpcional>)TempData["EstoqueOpcional" + PageToken]);
if (estoqueOpcionals.Where(x => x.DsOpcional == estoqueOpcional.DsOpcional).Count() == 0)
estoqueOpcionals.Add(estoqueOpcional);
TempData["EstoqueOpcional" + PageToken] = estoqueOpcionals;
return true;
}
public bool RemoverOpcional(string opcional, string PageToken)
{
try
{
if (TempData["EstoqueOpcional" + PageToken] != null)
{
List<EstoqueOpcional> estoqueOpcionals = (List<EstoqueOpcional>)TempData["EstoqueOpcional" + PageToken];
estoqueOpcionals.RemoveAll(x => x.DsOpcional == opcional);
TempData["EstoqueOpcional" + PageToken] = estoqueOpcionals;
}
return true;
}
catch
{
return false;
}
}
In the update button button of my main model I have done like this:
List<EstoqueOpcional> estoqueOpcionals = new List<EstoqueOpcional>();
if (TempData["EstoqueOpcional" + PageToken] != null)
estoqueOpcionals.AddRange((List<EstoqueOpcional>)TempData["EstoqueOpcional" + PageToken]);
foreach (var estoqueopcional in estoqueOpcionals)
{
estoqueopcional.CdEstoque = estoque.CdEstoque;
EstoqueOpcional estoqueopcionaltemp = db.EstoqueOpcional.Where(x => x.DsOpcional == estoqueopcional.DsOpcional).FirstOrDefault();
if (estoqueopcionaltemp == null)
db.EstoqueOpcional.Add(estoqueopcional);
}
foreach (var item in db.EstoqueOpcional.Where(x => x.CdEstoque == estoque.CdEstoque).ToList()
.Where(x => !estoqueOpcionals.Any(y => y.DsOpcional == x.DsOpcional)).ToList())
{
db.EstoqueOpcional.Remove(item);
}
The create method it's very familiar with the update one.
I still believe there must be a easier way to do this, but this was suitable for me.
Image Result
Any advice or suggestion is welcome.
Thanks.
I'm trying to specify headers and footers in a PDF generated by Rotativa library. As the author answered here it should be possible using CSS (described here). However, I'm not able to do this.
I have a stylesheet loaded in the meta tag:
<link href="print.css" rel="stylesheet" type="text/css" media="print" />
And in the stylesheet at the bottom:
#page {
#top-left {
content: "TOP SECRET";
color: red
}
#bottom-right {
content: counter(page);
font-style: italic
}
}
And then generating PDF by:
public ActionResult ShowPdf()
{
var model = new Model();
return new ViewAsPdf("view.cshtml", model)
{
FileName = "Report.pdf",
CustomSwitches = "--print-media-type"
};
}
And then nothing appears in the header and footer of the PDF. Any ideas?
I've found a documentation of wkhtmltopdf (or a better archived version) and it is described there how to manage headers and footers.
Basically you can just add --header-center "text" (or similar switches) to the argument list and that's all.
So using it with Rotativa it would be:
public ActionResult ShowPdf()
{
var model = new Model();
return new ViewAsPdf("view.cshtml", model)
{
FileName = "Report.pdf",
CustomSwitches = "--print-media-type --header-center \"text\""
};
}
(I don't know if --print-media-type is necessary.)
If you wanted to display a View instead of text in the header/footer then you can do so like this:
public ActionResult ViewPDF()
{
string customSwitches = string.Format("--print-media-type --allow {0} --footer-html {0} --footer-spacing -10",
Url.Action("Footer", "Document", new { area = ""}, "https"));
return new ViewAsPdf("MyPDF.cshtml", model)
{
FileName = "MyPDF.pdf",
CustomSwitches = customSwitches
};
}
[AllowAnonymous]
public ActionResult Footer()
{
return View();
}
Don't forget to add the [AllowAnonymous] attribute on the Footer action otherwise Rotatina can't get access to the path.
Here is how I did it (in full):
public ActionResult PrintPDF(int? selectedSiteRotaId, int selectedSiteId)
{
string footer = "--footer-center \"Printed on: " + DateTime.Now.Date.ToString("MM/dd/yyyy") + " Page: [page]/[toPage]\"" + " --footer-line --footer-font-size \"9\" --footer-spacing 6 --footer-font-name \"calibri light\"";
return new ActionAsPdf("RenderPDF", new { selectedSiteRotaId = selectedSiteRotaId, selectedSiteId = 7 })
{
FileName = "PDF_Output.pdf",
PageOrientation = Orientation.Landscape,
MinimumFontSize = 10,
//PageMargins = new Margins(5,5,5,5),
PageSize = Size.A3,
CustomSwitches = footer
};
//var pdfResult = new ActionAsPdf("RenderPDF", new { selectedSiteRotaId = selectedSiteRotaId, selectedSiteId = 7 })
//{
// FileName = "PDF_Output.pdf",
// PageOrientation = Orientation.Landscape,
// MinimumFontSize = 10
//};
//var binary = pdfResult.BuildPdf(this.ControllerContext);
//return File(binary, "application/pdf");
}
public ActionResult RenderPDF(int? selectedSiteRotaId, int selectedSiteId)
{
return RedirectToAction("Index", "PrintPDF", new { selectedSiteRotaId = selectedSiteRotaId, selectedSiteId = 7 });
}
string customSwitches = string.Format("--header-spacing \"0\" --footer-spacing \"0\" --footer-html {0} ", Url.Action("Footer", "Invoice", new { }, "http"));
return new ViewAsPdf(saleInvoiceVm)
{
PageOrientation = Orientation.Portrait,
PageSize = Rotativa.AspNetCore.Options.Size.A4,
PageMargins = { Left = 5, Bottom = 25, Right = 7, Top = 10 },
CustomSwitches = customSwitches,
};
try it it will work 100 %
return new ViewAsPdf("MyPDF.cshtml", model)
{
FileName = "MyPDF.pdf",
CustomSwitches = customSwitches
};
}
I use the AsyncUpload
<telerik:RadAsyncUpload runat="server" ID="rada_attach" OnClientFileUploaded="onClientFileUploaded"
MultipleFileSelection="Disabled" InitialFileInputsCount="1" MaxFileInputsCount="1"
Width="100%" />
function onClientFileUploaded(radAsyncUpload, args) {
var row = args.get_row(),
inputName = radAsyncUpload.getAdditionalFieldID("TextBox"),
inputType = "text",
inputID = inputName,
input = createInput(inputType, inputID, inputName),
label = createLabel(inputID),
br = document.createElement("br");
row.appendChild(br);
row.appendChild(input);
row.appendChild(label);
}
function createInput(inputType, inputID, inputName) {
var input = document.createElement("input");
input.setAttribute("type", inputType);
input.setAttribute("id", inputID);
input.setAttribute("name", inputName);
return input;
}
I want to access the textbox (which created dynamically) in .cs.
How to do that ?
The Full Answer :
var $ = $telerik.$;
function onClientFileUploaded(radAsyncUpload, args) {
var $row = $(args.get_row());
var inputName = radAsyncUpload.getID("TextBox");
var inputType = "text";
var inputID = inputName;
var input = createInput(inputType, inputID, inputName);
var label = createLabel(inputID);
$row.append("<br/>");
$row.append(label);
$row.append(input);
}
function createInput(inputType, inputID, inputName) {
var input = '<input type="' + inputType + '" id="' + inputID + '" name="' + inputName + '" />';
return input;
}
function createLabel(forArrt) {
var label = '<label for=' + forArrt + '>info: </label>';
return label;
}
foreach (UploadedFile UF in rada_attach.UploadedFiles)
{
if (UF.GetFieldValue("TextBox") != null)
{
OBJ.File_name = UF.GetFieldValue("TextBox");
}
else
{
OBJ.File_name = UF.GetName();
}
In my opinion documentation is well clear. Check the Description tab on page you refer on. You can access value of dynamic textboxes with code below on postback:
if (rada_attach.UploadedFiles.Count > 0) {
for (var index = 0; index < rada_attach.UploadedFiles.Count; ++index) {
var textBoxValue = rada_attach.UploadedFiles[index].GetFieldValue("TextBox");
}
}
BTW, this scenario is well-dcoumented here: Adding Information to Uploaded Files
You need to check the Request.Form values (that were in the posted form) on postback and perform a check on all the fields that were posted back.
I am guessing that you won't know the name/id of the textbox if it was created on the client-side dynamically? Note that it would be the name of the form field that the Request object in .cs would see.
Only once you have posted back can you access that value in the .cs
I got an ActionResult TabNotes which returns a View for a tab which shows notes from a database in a grid. On the tab is a button for ActionResult CreateNote, which returns a PartialView and after saving the note I redirect back to the ActionResult TabNotes with
return RedirectToAction("TabNotes", new { modelEntity = "Phrase", id = itemId});
However, when it goes to the action result TabNotes using this redirect it does not show the grid. The javascript gives the following error
Uncaught ReferenceError: $ is not defined (anonymous function)
Uncaught ReferenceError: ko is not defined (anonymous function)
This does not happen the first time it goes to ActionResult. Using breakpoints the following part of the ActionResult TabNotes:
[...]
Model.Grid.url = Url.Action("TabNoteData", new { id = Model.meta.entity, itemId = Model.meta.id.Value});
}
return View("TabNotes", Model);
}
gives the same input values in Model for the first time and the second time. Where can this error come from?
Edit: Firebug shows the following errors:
prompt aborted by user
throw Components.Exception...by user", Cr.NS_ERROR_NOT_AVAILABLE); nsPrompter.js (regel 462 <Systeem>
$ is not defined
$(document).ready(function(){$('#tblTN...tes/44?cmd=refresh" id="TNPhrase44"> 44?mod...=Phrase (regel 2)
ko is not defined
var viewModel=ko.mapping.fromJ...],"buttons":[],"PostAction":null}}); 44?mod...=Phrase (regel 12)
Below is the javascript and code
#model test.Web.Framework.Areas.Administration.Models.TabNotesModel
#using (UI.DocumentReadyScript())
{
if (Model.meta.id.HasValue)
{
UI.jQuery("#tbl" + Model.meta.modelname).flexigrid(Model.Grid);
}
}
<form method="post" action="#Url.Action("TabNotes", new { cmd = "refresh" })" id="#Model.meta.modelname">
<div class="ui-state-highlight ui-corner-all highlight" data-bind="visible: meta.message">
<span class="ui-icon ui-icon-info"></span><strong data-bind="text: meta.message">
</strong>
</div>
#using (UI.BeginBlock("Administation.TabNotes", UI.Label("Notes", "Notes").ToString(), test.Web.Framework.Core.enumIcons.pencil, false, false))
{
<table id="#("tbl" + Model.meta.modelname)">
</table>
}
</form>
<script type="text/javascript">
(function() {
var viewModel=ko.mapping.fromJS(#Html.Raw(UI.JavascriptEncode(Model)));
viewModel.getData=function() { return ko.mapping.toJSON( this ); };
viewModel.setData=function(data){
$('#tbl'+this.meta.modelname()).flexigrid( data.Grid);
ko.mapping.updateFromJS(this,data);
};
$('##Model.meta.modelname').koform({viewmodel: viewModel , validate : {errorElement:'p' } } );
$('##Model.meta.modelname').koform('applyBindings');
$('#load-partial').click(function() {
$('#partial').load('#Url.Action("CreateNote", "Entity", new {itemId = #Model.meta.id, modelEntity = "Phrase"})');
});
})();
</script>
<div id="partial"></div>
<button type="button" id="load-partial">Create Note</button>
'
public ActionResult CreateNote(
[ModelBinder(typeof(Models.JsonModelBinder))]
NoteModel Model, string cmd, long? itemId, string modelEntity)
{
if (cmd == "Save")
{
Model.meta.message = "Note saved";
test.Database.User User = UserRepository.GetUser(1);
Entity entity = NotesRepository.GetEntity("Phrase");
NotesRepository.StoreNote(Model.subject, Model.text, User, entity, itemId);
return RedirectToAction("TabNotes", new { modelEntity = "Phrase", id = itemId});
}
Model.meta.modelname = "CreateNote";
Model.meta.JsViewModelType = "EditNoteModel";
Model.meta.PostAction = Url.Action("CreateNote", new { cmd = "Save", itemId = itemId});
return PartialView("CreateNotePartial",Model);
}
'
public ActionResult TabNotes([ModelBinder(typeof(Models.JsonModelBinder))]
TabNotesModel Model, string cmd, string modelEntity, long? id)
{
if (modelEntity != null)
{
Model.meta.entity = modelEntity;
}
Entity entity = NotesRepository.GetEntity(Model.meta.entity);
if (id.HasValue)
{
Model.meta.id = id;
}
if (Model.meta.id.HasValue)
{
Model.meta.modelname = "TN" + Model.meta.entity + Model.meta.id.Value.ToString();
Dictionary<string, object> defaultValues = new Dictionary<string, object>();
defaultValues.Add("Entity", entity.EntityId);
defaultValues.Add("ItemId", Model.meta.id.Value);
Entity noteEntity = NotesRepository.GetEntity("Note");
var grid = UI.GetEntityFlexiGrid(noteEntity, true, true, true, true, defaultValues);
grid.buttons.Clear();
//grid.buttons.Add(new Button { onpress = "CreateNote", action = Url.Action("CreateNote"), name = "CreateNote", postdata = new { meta = Model.meta }});
grid.title = "";
Model.Grid = grid;
Model.Grid.url = Url.Action("TabNoteData", new { id = Model.meta.entity, itemId = Model.meta.id.Value});
}
return View("TabNotes", Model);
}
'
public GridResult TabNoteData(string id, long itemId, FlexigridRequest request, string cmd)
{
GridResult returnValue = null;
var entity = NotesRepository.GetEntity(id);
Entity noteEntity = NotesRepository.GetEntity("Note");
//var Acess = UIRepository.GetEntityAccess(id);
FlexigridConfiguration grid;
Dictionary<string, object> defaultValues = new Dictionary<string, object>();
defaultValues.Add("Entity", entity.EntityId);
defaultValues.Add("ItemId",itemId);
grid = UI.GetEntityFlexiGrid(noteEntity, true, true, true, true, defaultValues);
IQueryable q = NotesRepository.GetNotes(entity.EntityId, itemId);
var sortField = entity.EntityFields.SingleOrDefault(c => c.Name == request.sortname);
if (sortField == null)
{
request.sortname = grid.sortname;
}
IQueryable qdata = null;
if (!string.IsNullOrEmpty(request.sortname) && request.sortname != "undefined")
{
switch (request.sortorder)
{
case enumFlexigridRequestSortOrder.asc:
qdata = q.OrderBy(request.sortname + " ascending");
break;
case enumFlexigridRequestSortOrder.desc:
qdata = q.OrderBy(request.sortname + " descending");
break;
}
}
if (!string.IsNullOrEmpty(request.query) && !string.IsNullOrEmpty(request.qtype))
{
qdata = qdata.Where(request.qtype.SanitizeFieldExpression() + ".Contains(#0)", request.query);
}
if (request.q != null && request.q.Length > 0)
{
for (int i = 0; i < request.q.Length; i++)
{
var type = UIRepository.GetType(id);
var property = type.GetProperty(request.q[i]);
System.ComponentModel.TypeConverter tc = System.ComponentModel.TypeDescriptor.GetConverter(property.PropertyType);
string sv = request.v[i];
if (sv == null || sv == "null")
{
qdata = qdata.Where(request.q[i].SanitizeFieldExpression() + "=#0", (object)null);
}
else
{
object v = tc.ConvertFromString(sv);
qdata = qdata.Where(request.q[i].SanitizeFieldExpression() + "=#0", v);
}
}
}
string settingName = "Grid." + id + ".Rp";
var setting = UIRepository.GetQuery<test.Database.UserSetting>().SingleOrDefault(uc => uc.CreatedById == CurrentUser.UserId && uc.Name == settingName);
if (setting == null)
{
setting = UIRepository.Create<test.Database.UserSetting>();
setting.Name = settingName;
setting.Value = request.rp.ToString();
UIRepository.Add(setting);
}
else
{
if (request.rp.ToString() != setting.Value)
{
setting.Value = request.rp.ToString();
UIRepository.Update(setting);
}
}
int rowId = 0;
var datarows = new List<object>();
foreach (var record in qdata.Skip((request.page - 1) * request.rp).Take(request.rp).GetData())
{
var cellValues = new List<object>();
foreach (var gc in grid.colModel.OrderBy(c => c.di))
{
cellValues.Add(gc.ToString(UI, record));
}
var row = new { id = rowId, cell = cellValues.ToArray() };
datarows.Add(row);
rowId++;
}
returnValue = Grid(request.page, qdata.Count(), datarows.ToList());
return returnValue;
}
That error can only be caused be one of three things:
Your JavaScript file is not being properly loaded into your page
You have a botched version of jQuery. This could happen because someone edited the core file, or a plugin may have overwritten the $ variable.
You have JavaScript running before the page is fully loaded, and as such, before jQuery is fully loaded.
You should check the Firebug net panel to see if the file is actually being loaded properly. If not, it will be highlighted red and will say "404" beside it. If the file is loading properly, that means that the issue is number 2.
Make sure all javascript code is being run inside a code block such as:
$(document).ready(function () {
//your code here
});
This will ensure that your code is being loaded after jQuery has been initialized.
One final thing to check is to make sure that you are not loading any plugins before you load jQuery. Plugins extend the "$" object, so if you load a plugin before loading jQuery core, then you'll get the error you described.
So to avoid that you can use a "bodyguard" function like the following:
( function($) {
//We can now use $ as I implemented the bodyguard!
$(document).ready(function() {
//your code...
});
} ) ( jQuery );