JQuery, updating form and exception if update it more then once - asp.net-mvc-2

I've got index of my elements:
<h2>Index</h2>
<script type="text/javascript"
src="http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js"></script>
<script type="text/javascript">
$(document).ready(function () {
$('button').click(function () {
$.post("Home/Swap", $("#log").serialize(), function (data) {
$("#log").load("Home/Index #log");
});
});
});
</script>
<form name="list" action="<%=Url.Action("Post", "Home")%>" method="post" id="log">
<% foreach (var k in Model) { %>
<input type="checkbox" id="ids" name="ids" value="<%=k.pos%>" /><%= k.pos %>. To jest numer: <%=k.name%><br />
<% } %>
</form>
<button>Swap</button>
and Swap method:
public ActionResult Swap(int[] ids)
{
int pos1=ids[0];
int pos2=ids[1];
Element element1 = (from t in db.Elements
where t.pos == pos1
select t).Single();
Element element2 = (from t in db.Elements
where t.pos == pos2
select t).Single();
element1.pos = pos2;
element2.pos = pos1;
db.SaveChanges();
return Index();
}
Everything works fine at the first swap of elements. But when I swap it once, and then try to swap another two I get an exception:
System.NullReferenceException was
unhandled by user code
Message=Object reference not set to an
instance of an object.
(exception from Swap Method)
It's JQuery problem, Im sure. I susspect this $("#log").load("Home/Index #log"); line - it shows me right result, but doesn't work fine if I try to do it more then once. how to fix it?
edit: when I refresh page it works the same -> first works well, after getting an exception (the first touched elements are swaped after refreshing)

When you do .load("url selector") it gets that element, not the contents of that element, so you end up with a nested <form>, so instead create a wrapper and load that wrapper, so you replace the <form>, like this:
<div id="wrapper">
<form name="list" action="<%=Url.Action("Post", "Home")%>" method="post" id="log">
<% foreach (var k in Model) { %>
<input type="checkbox" id="ids" name="ids" value="<%=k.pos%>" /><%= k.pos %>. To jest numer: <%=k.name%><br />
<% } %>
</form>
</div>
<button>Swap</button>
Then load that element instead, so you're replacing the <form>, like this:
$(function () {
$('button').click(function () {
$.post("Home/Swap", $("#log").serialize(), function (data) {
$("#wrapper").load("Home/Index #log");
});
});
});

Related

How to select the closest element with a specific tag in chai protractor

If the html looks as follow:
<form>
<div>
<field-component>
<div class='field'></div>
</field-component>
</div>
<div>
<div class='icon'></div>
</div>
</form>
I am able to get the field using fieldElement = element(by.css('.field')), but how can I get the closest element with the icon class?
try this:
var form = element(by.css('form'));
return form.element(by.css('.field')).isPresent().then((present) => {
if (present) {
return form.element(by.css('.icon')).click(); #click or whatever on this element
}
});

Error submitting form data using knockout and mvc

#model NewDemoApp.Models.DemoViewModel
#{
ViewBag.Title = "Home Page";
}
#*<script src="#Url.Content("~/Scripts/jquery-1.9.1.min.js")" type="text/javascript"></script>*#
<script src="http://code.jquery.com/jquery-1.11.3.min.js"></script>
<script src="http://code.jquery.com/jquery-migrate-1.2.1.min.js"></script>
<script src="#Url.Content("~/Scripts/knockout-3.3.0.js")" type="text/javascript"></script>
<script src="#Url.Content("~/Scripts/jquery.validate.min.js")" type="text/javascript"></script>
<script src="#Url.Content("~/Scripts/jquery.validate.unobtrusive.min.js")" type="text/javascript"></script>
<script type="text/javascript">
var viewModel;
var compViewModel, userViewModel;
$(document).ready(function () {
$(".wizard-step:visible").hide();
$(".wizard-step:first").show(); // show first step
$("#back-step").hide();
var result = #Html.Raw(Json.Encode(Model));
var viewModel = new DemoViewModel(result.userViewModel);
//viewModel.userViewModel.FirstName = result.userViewModel.FirstName;
//viewModel.userViewModel.LastName = result.userViewModel.LastName;
//viewModel.userViewModel.State = result.userViewModel.State;
//viewModel.userViewModel.City = result.userViewModel.City;
ko.applyBindings(viewModel);
});
var userVM = function(){
FirstName = ko.observable(),
LastName = ko.observable(),
State = ko.observable(),
City = ko.observable()
};
function DemoViewModel(data) {
var self = this;
self.userViewModel = function UserViewModel(data) {
userVM.FirstName = data.FirstName;
userVM.LastName = data.LastName;
userVM.State = data.State;
userVM.City = data.City;
}
self.Next = function () {
var $step = $(".wizard-step:visible"); // get current step
var form = $("#myFrm");
var validator = $("#myFrm").validate(); // obtain validator
var anyError = false;
$step.find("input").each(function () {
if (!validator.element(this)) { // validate every input element inside this step
anyError = true;
}
});
if (anyError)
return false; // exit if any error found
if ($step.next().hasClass("confirm")) { // is it confirmation?
$step.hide().prev(); // hide the current step
$step.next().show(); // show the next step
$("#back-step").show();
$("#next-step").hide();
//$("#myFrm").submit();
// show confirmation asynchronously
//$.post("/wizard/confirm", $("#myFrm").serialize(), function (r) {
// // inject response in confirmation step
// $(".wizard-step.confirm").html(r);
//});
}
else {
if ($step.next().hasClass("wizard-step")) { // is there any next step?
$step.hide().next().fadeIn(); // show it and hide current step
$("#back-step").show(); // recall to show backStep button
$("#next-step").show();
}
}
}
self.Back = function () {
var $step = $(".wizard-step:visible"); // get current step
if ($step.prev().hasClass("wizard-step")) { // is there any previous step?
$step.hide().prev().fadeIn(); // show it and hide current step
// disable backstep button?
if (!$step.prev().prev().hasClass("wizard-step")) {
$("#back-step").hide();
$("#next-step").show();
}
else {
$("#back-step").show();
$("#next-step").show();
}
}
}
self.SubmitForm = function (formElement) {
$.ajax({
url: '#Url.Content("~/Complaint/Save")',
type: "POST",
data: ko.toJS(self),
done: function (result) {
var newDiv = $(document.createElement("div"));
newDiv.html(result);
},
fail: function (err) {
alert(err);
},
always: function (data) {
alert(data);
}
});
}
self.loadData = function () {
$.get({
url: '#Url.Content("~/Complaint/ViewComplaint")',
done: function (data) {
debugger;
alert(data);
self.compViewModel(data);
self.userViewModel(data);
},
fail: function (err) {
debugger;
alert(err);
},
always: function (data) {
debugger;
alert(data);
}
});
}
}
</script>
<form class="form-horizontal" role="form" id="myFrm">
<div class="container">
<div class="row">
<div class="col-md-3">
</div>
<div class="col-md-6">
<div class="wizard-step">
</div>
<div class="wizard-step" >
<h3> Step 2</h3>
#Html.Partial("UserView", Model.userViewModel)
<div class="col-md-3"></div>
<div class="col-md-6">
<input type="submit" id="submitButton" class="btn btn-default btn-success" value="Submit" data-bind="click: SubmitForm" />
</div>
<div class="col-md-3"></div>
</div>
<div class="wizard-step">
<h3> Step 3</h3>
</div>
<div class="wizard-step confirm">
<h3> Final Step 4</h3>
</div>
</div>
<div class="col-md-3"></div>
</div>
<div class="row">
<div class="col-md-3"></div>
<div class="col-md-6">
<input type="button" id="back-step" class="btn btn-default btn-success" value="< Back" data-bind="click: Back" />
<input type="button" id="next-step" class="btn btn-default btn-success" value="Next >" data-bind="click: Next" />
</div>
<div class="col-md-3"></div>
</div>
</div>
</form>
I am able to get the data from controller and bind it using knockout. There is a partial view that loads data from controller. But when submitting the updated data, I do not get the data that was updated, instead getting error that "FirstName" property could not be accessed from null reference. I just need to get pointers where I am going wrong especially the right way to create ViewModels and use them.
When you are submitting the form in self.SubmitForm function you are passing Json object which is converted from Knockout view model.
So make sure you are providing the data-bind attributes in all input tags properly. If you are using Razor syntax then use data_bind in Html attributes of input tags.
Check 2-way binding of KO is working fine. I can't be sure as you have not shared your partial view Razor code.
Refer-
http://knockoutjs.com/documentation/value-binding.html
In Chrome you can see what data you are submitting in Network tab of javascript developer console. The Json data that you are posting and ViewModel data structure you are expecting in controller method should match.
You can also change the parameters to expect FormCollection formCollection and check what data is coming from browser when you are posting.

Set selected Kendo menu item with HtmlAttributes to hiddem form field

i have a kendo menu that is bound to my form by the onclick event like this
#(Html.Kendo().Menu()
.Name("MenuCreate")
.Items(items =>
{
items.Add().Text("<<").Action("Index", "BSfune");
items.Add().Text("New").HtmlAttributes(new{onclick = "getElementById('FormCreate').submit()", #id = "New"});
items.Add().Text("Edit").HtmlAttributes(new { onclick = "getElementById('FormCreate').submit()", #id = "Edit" });
})
.Events(e => e.Select("select"))
)
and in my form i have a hiden field called FormmMode
#using (Html.BeginForm("Create", "BSfune", FormMethod.Post, new { id = "FormCreate" }))
{
#Html.AntiForgeryToken()
#Html.ValidationSummary(true)
<div class="form">
<fieldset>
<legend>#ViewBag.Title</legend>
<div>
<div>
(My form code)
</div>
#Html.HiddenFor(model => model.FormMode, new { #id = "FormMode"})
<br />
<br />
<br />
</div>
</fieldset>
</div>
}
i want to set my field form (FormMode) with the selected menuitem text "New" or "Edit".
I noticed that the onclick overrides the selected event. So.. It would be something like this
<script type="text/javascript">
$(function () {
$('#New').on('click', function () {
$("#FormMode").val($(this).text());
});
});
function select(e) {
}
But this does not work..
On the controler side i have
public ActionResult Create(CrBSfune p_BSfune)
{
(...)
if (p_BSfune.FormMode == "New")
return RedirectToAction("Create");
else
return RedirectToAction("Index");
}
But my p_BSfune.FormMode is null.
Can you help?
Thanks.:)
Got it!!! Catching the click event was the solution, the way to pass the value.. that was more trickie.. but after several attempts got it.:) did this and it works fine.:)
$('#New').click(function (e) {
e.preventDefault();
$('#FormCreate')[0].FormMode.value = e.target.innerText;
$('#FormCreate').submit();});
Don't know if it is the best approach.. but it works.:)

MVC2 ajax partial view does not register jquery scripts

I have my page where i have ajax call to display form.
My code works when the register the code for form but not from postback (validation error in controller).
any idea how to fix this?
My container page has:
Scripts:
<%= Html.JQuery() %>
<script src="../../../../Scripts/jquery.ui.core.js" type="text/javascript"></script>
<script src="../../../../Scripts/jquery.ui.datepicker.min.js" type="text/javascript"></script>
<script src="../../../../Scripts/MicrosoftAjax.js" type="text/javascript"></script>
<script src="../../../../Scripts/MicrosoftMvcAjax.js" type="text/javascript">/script>
<script src="../../../../Scripts/MicrosoftMvcValidation.js" type="text/javascript"></script>
<script type="text/javascript">
function registerStuff() {
//this gets triggered when onsuccess is called
$("#date").datepicker({ dateFormat: 'dd/mm/yy' });
$("#sla").datepicker();
}
</script>
Content:
<%= Ajax.AjaxButton("New action", "CreateWorkFlowAction", new {
controller = "CaseWorkFlow" }, new AjaxOptions() { UpdateTargetId =
"divTableContainer", HttpMethod = "Get", OnSuccess =
"registerStuff"})%>
<div id="divTableContainer">
response will appear here
</div>
my form looks like
<script type="text/javascript">
function RegisterJs() {
$("#date").datepicker({ dateFormat: 'dd/mm/yy' });
$("#sla").datepicker({ dateFormat: 'dd/mm/yy' });
}
</script>
<% Html.EnableClientValidation(); %>
<% using (Ajax.BeginForm("CreateWorkFlowAction", new AjaxOptions() { UpdateTargetId = "divTableContainer", HttpMethod = "Post" }))
{%>
<%= Html.ValidationSummary() %>
<fieldset>
<div>
<label for="title">
Title</label>
<%= Html.TextBoxFor(x=>x.Title) %>
</div>
<div>
<label for="SLA">
SLA(Due Date)</label>
<%= Html.TextBoxFor(x => x.SelectSlaDate, new { id = "sla", #Value = string.Empty} )%>
</div>
<div>
<label for="date">
Date</label>
<%= Html.TextBoxFor(x => x.SelectDate, new { id = "date", #Value = string.Empty})%>
</div>
<div>
<button type="submit">Save action</button>
</div>
</fieldset>
<% } %>
the problem is
i have found the solution to my question.
I have to reregister my javascript inside of a partial view.
this means that i had to update add register scripts into the parent page to which i will insert partial view.
and therfore if my view page contains partial view i had to move
function registerStuff() {
//this gets triggered when onsuccess is called
$("#date").datepicker({ dateFormat: 'dd/mm/yy' });
$("#sla").datepicker();
}
to the index page.
After on success call this function "registerStuff" from my oncomplete,
and after then everything is working like charm
hope this helps to you too

dynamic creation of textbox

while i create textbox dynamically i can able to add any no
of textbox while i delete only last textbox got deleted after it
an throws exception.
<html>
<head>My page </html>
<body>
<div id="firstdiv">
<input type="text" id="text" id="text1" value=""/>
<input type="button" id="butt" name="it's okay" value="+" onclick="text_add()"/>
<input type="button" id="butt1" name="it's okay" value="-" nclick="text_remove()"/>
</div>
</body>
<script type="text/javascript">
var i=0;
function text_add()
{
++i;
var bal=document.createElement("input")
bal.setAttribute("type","text");
bal.setAttribute("id","text"+i);
bal.setAttribute("name","bala");
firstdiv.appendChild(bal);
}
function text_remove()
{
try{
var a="\"";
a+="text"+(i);
a+="\"";
alert(a);
var bal=document.getElementById(a);
firstdiv.removeChild(bal);
--i;
}catch(e)
{
alert("Echo"+e);
}
}
</script>
</html>
chorme throws error: after deleting one text box like
EchoError: NOT_FOUND_ERR: DOM Exception 8
so you whant to add and remove textboxes.
and the latest textbox added shuld be removed?
so first you alreddy have a textbox in the dom witch will colide with your
naming
<input type="text" id="text" id="text1" value=""/>
is this an atemt to manualy add qoutes ? becus thats not part of the id
of the element
var a="\"";
a+="text"+(i);
a+="\"";
just give it the name normaly
var bal = document.getElementById("text" + i);
and you dont have to mess around with dom ids you can store
dom elements as normal objects so
something like this works fine
var textElements = [];
var firstdiv = document.getElementById("firstdiv");
function text_add() {
var bal = document.createElement("input");
bal.setAttribute("type","text");
bal.setAttribute("name","bala");
firstdiv.appendChild(bal);
textElements.push(bal);
}
function text_remove() {
firstdiv.removeChild(textElements.pop());
}
the pop method removes the last added item in the array