jquery input selector with li - c#

I have list of input textbox with class="txtdate"
and
list of another input textbox with class ="txthrs"
like
<div id="dvlitr"><li id="0"><label class="txtdatewrapper"><input type="text" placeholder="Select Date" class="txtdate hasDatepicker" value="" readonly="" id="txtsDate1"><span class="txtdateicon"></span> </label><input type="text" placeholder="Hrs" class="txthours" value="" id="txtsHrs1"><a title="Add" class="btnadd" href="javascript:void(0)"></a><a title="Delete" id="btndelnewli1" class="btndelete" href="javascript:void(0)"></a><input type="hidden" placeholder="Hrs" value="0" id="iDhdn0"></li><li id="2"><label class="txtdatewrapper"><input type="text" placeholder="Select Date" class="txtdate hasDatepicker" readonly="" id="txtsDate2" value="10/28/2013"><span class="txtdateicon"></span></label> <input type="text" placeholder="Hrs" class="txthours" id="txtsHrs2"><a title="Add" class="btnadd" href="javascript:void(0)"></a><a title="Delete" id="btndelnewli2" class="btndelete" href="javascript:void(0)"></a><input type="hidden" placeholder="Hrs" value="0" id="iDhdn2"></li><li id="3"><label class="txtdatewrapper"><input type="text" placeholder="Select Date" class="txtdate hasDatepicker" readonly="" id="txtsDate3" value="10/30/2013"><span class="txtdateicon"></span></label> <input type="text" placeholder="Hrs" class="txthours" id="txtsHrs3"><a title="Add" class="btnadd" href="javascript:void(0)"></a><a title="Delete" id="btndelnewli3" class="btndelete" href="javascript:void(0)"></a><input type="hidden" placeholder="Hrs" value="0" id="iDhdn3"></li></div>
I have to find is there any li with empty date or empty hrs (any one of them)
i tried something like this
var count = $('#dvlitr > li').filter(function() {
var $txtdate = $(this).children('.txtdate').val();
var $txthrs = $(this).children('.txthrs').val();
return (($.trim($txtdate) != '' && $.trim($txthrs) === '') || ($.trim($txtdate) === '' && $.trim($txthrs) != ''))
}).length;
alert(count);
fiddle
but dint get the desired result
please help
Thanks

After looking to your correct HTML markup, you can do this:
var count = $('li').filter(function () {
var $txtdate = $(this).children('.txtdate').val();
var $txthrs = $(this).children('.txthrs').val();
return ($.trim($txtdate) === '' && $.trim($txthrs) === '')
}).length;
console.log('count: ' + count);
Demo: Fiddle
UPDATE
You can do this:
var count = $('li').filter(function () {
var $txtdate = $(this).find('.txtdate').val();
var $txthrs = $(this).find('.txthrs').val();
return ($.trim($txtdate) === '' && $.trim($txthrs) === '')
}).length;

Remove ":" before "input"... will be better but didn't do the trick!
See Jquery selectors doc for more informations
And you make some mistakes. I thing this one should be correct now :
var count = $("li > input.txtdate[value='']+
input.txthrs[value='']").length;
You want to retrieve only the number of li where both of txtdate and txthrs are empty?
You can see it in action in this updated palash fiddle
To complete, in the case that empty value are in fact when value attrib missing, use this one :
var count = $("li > input.txtdate:not([value])+
input.txthrs:not([value])").length;
To be sure to have value attrib : $('input[type=text']:not([value])).attr('value','');
To retrieve the number of line with almost one of field empty, use this :
var count = $.unique($("li").has("input.txtdate[value=],input.txtdate:not([value]),input.txthrs[value=],input.txthrs:not([value])")).length;
Update
$('input:not([value])').attr('value', '');
//Getting only lines when one of input is empty
$.unique($("li").has("input.txtdate[value=''],input.txthrs[value='']")).length;
//Getting only lines when both inputs are empty
$("li > input.txtdate[value='']+input.txthrs[value='']").length;
Trust me, or not...
UPDATE with new DOM input aren't direct child of li
$('input:not([value])').attr('value', '');
//Getting only lines when one of input is empty
$.unique($("li").has("input.txtdate[value=''],input.txthrs[value='']")).length;
//Getting only lines when both inputs are empty
$("li input.txtdate[value='']+input.txthrs[value='']").length;
I wake up... sorry! So you was right form the beginning, with simple selector, you can't detect a user update of a input! Sorry I was wrong!
I founded this plugin here :
jQuery.extend(
jQuery.expr[':'],
{
/// check that a field's value property has a particular value
'field-value': function (el, indx, args) {
var a, v = $(el).val();
if ( (a = args[3]) ) {
switch ( a.charAt(0) ) {
/// begins with
case '^':
return v.substring(0,a.length-1) == a.substring(1,a.length);
break;
/// ends with
case '$':
return v.substr(v.length-a.length-1,v.length) ==
a.substring(1,a.length);
break;
/// contains
case '*': return v.indexOf(a.substring(1,a.length)) != -1; break;
/// equals
case '=': return v == a.substring(1,a.length); break;
/// not equals
case '!': return v != a.substring(1,a.length); break;
/// equals
default: return v == a; break;
}
}
else {
return !!v;
}
}
}
);
Wich allow you to make some selecotr like this :
$('input:field-value(=)');//for empty
$.unique($("li").has("input.txtdate:field-value(=),input.txthrs:field-value(=)")).length;

try this. It will retrieve all the inputs and iterate through them.
var count = 0;
$('.txtdate, .txthrs').each(function (){
if($(this).val() == '') { //If inspects if the input has an empty value
//Do something here if the value is empty
//can add css to change the color or
//assign class to it or call method, etc
count++;
}
});
console.log('count: ' + count);

Related

Form fields in array uniquely identified with item Id - how to access their values in the controller?

Let's say I have this dynamically created form:
<form>
Item #1 <input type="text" name="qty" id="Item_3223" value="3">
Item #2 <input type="text" name="qty" id="Item_2243" value="1">
Item #3 <input type="text" name="qty" id="Item_5328" value="1">
Item #4 <input type="text" name="qty" id="Item_3250" value="5">
<!--... and so on...-->
<button type="submit">Update quantities</button>
</form>
The fields are generated server side like this:
<input type="text" name="qty" id="Item_#item.Id" value="#item.Qty">
In my controller, how can I receive the array and perform an update on each of the items in it?
Simplified, my Update-method looks like this now:
public async Task<IActionResult> Update(IFormCollection form)
{
var updateItem = new ShoppingCartItem();
foreach (string item in form.Keys)
{
updateItem = (from c in _context.ShoppingCartItems
where (c.ShoppingCartId == ShoppingCartItem.ShoppingCartId &&
c.ProductId == form.[what goes here?])
select c).FirstOrDefault();
updateItem.Quantity = form.[what goes here?]
}
_context.SaveChangesAsync();
return RedirectToAction("Index", "Cart");
}
Since I can't know the name of the form.Keys, how can I extract the values from them? I seem to remember this was quite easy in classic ASP back in the day ...
Edit
With help from #David, I put this together:
<input asp-for="#item.Quantity" name="Item_#item.ProductId" id="Item_#item.ProductId" />
... and:
var updateItem = new ShoppingCartItem();
int qty = 0;
int pId = 0;
foreach (string item in form.Keys.Where(k => k.StartsWith("Item_")))
{
pId = int.Parse(item.Replace("Item_", ""));
updateItem = (from c in _context.ShoppingCartItems
where (c.ShoppingCartId == ShoppingCartItem.ShoppingCartId && c.ProductId == pId)
select c).FirstOrDefault();
qty = int.Parse(form[item]);
updateItem.Quantity = qty;
}
await _context.SaveChangesAsync();
Works like a charm! Thanks! :)
You're not passing an array to the server-side code. You're passing a single value with the name "qty". This would likely be the last instance of that input in your form.
An array needs brackets in the name:
<input type="text" name="qty[]" id="Item_#item.Id" value="#item.Qty">
Then in the server-side code the "key" for the array is "qty[]". You can pull that array from the form object and iterate over it for your needs:
var inputArray = form["qty[]"];
Basically, all you need is the brackets in the name to tell the browser that these multiple elements constitute an array of values. The id has nothing to do with form posting.
Edit: If you do need that "id" value, then you can put it in the name:
<input type="text" name="Item_#item.Id" id="Item_#item.Id" value="#item.Qty">
Then you would have multiple unique key/value pairs in the form post, which you can check as you're currently attempting to (foreach (string item in form.Keys)) and then parse out the "id" from that item string as needed.
It sounds like what you need is a dictionary. For that, you'd need inputs like the following:
<input type="hidden" name="qty[0].Key" value="#item.Id" />
<input type="text" name="qty[0].Value" value="#item.Qty" />
You'd bind that to a param like Dictionary<int, int> qty. Then, you can access the quantities for each item via something like:
item.Qty = qty[item.Id];
That said, it's usually better to just use view models for this kind of thing, so you can bind to properties in a strongly-typed way. For example, you could use something like:
public class ItemQuantityViewModel
{
public int Id { get; set; }
public int Qty { get; set; }
}
Then, you can have as the model for your form (and the param you bind to on your action) be List<ItemQuantityViewModel>. Finally, you'd just have input like:
#for (var i = 0; i < Model.Count; i++)
{
<input type="hidden" asp-for="#Model[i].Id">
<input asp-for="#Model[i].Qty">
}

How to check and get value of lambda which has a value of string and expression

Declaration:
Func<dynamic,oject> format;
Provide value:
format: #<text> <input type="checkbox" checked="" /> </text>)
format: (itm) => { return itm.Name + " Somtheing <a>Click Here</a> "
Im looking for the output which is this,
Output 1. (here no problem)
<input type="checkbox" checked="" />
Output 2.
if (Itm.Name is "Rose")
then Output should be "Rose Somtheing <a>Click Here</a>")
but i got the error here which is
'System.Array' does not contain a definition for 'Name' ).
Here is the code
var obj = format.GetInvocationList();
var result = c.Format(obj);
Any sugesstion here?
Closed: Already found the solution to the problem.
What i did is get the current row in model or object that holds the current data
instead of using
var obj = format.GetInvocationList();
i changed it too
object row = GetCurrentRows();
var result = c.Format(row);
Check the spelling of item/itm
Try:
format: (item) => { return item.Name + " Somtheing <a>Click Here</a> "
Instead of:
format: (item) => { return itm.Name + " Somtheing <a>Click Here</a> "

javascript to dynamically add a textbox

I am trying to dynamically add a text box based on the selection of dropbox. When the user selects 'other' a text box gets generated asking them to explain the other. The user can dynamically add mutiple dropboxes, resulting in multiple text boxes if other is selected value in dropbox. Every generated dropbox has a unique name which gets read and placed in id of dynamically generated textbox.
The problem i am facing is that when there are multiple dropboxes and the first dropbox selection is something other that 'Other' and second dropbox value is other, the text box generated is placed in front of the first dropbox where it should be placed in front of the dropbox relevant to it.
The html code is as follows for the dropbox:
<div id="container">
<label id="rightlabel"for="dropbox1"></label>
<span>
<select id="frequency" onclick="getData(this, name)" name="dropbox[4fb103e3-06e7-4c88-8836-73b855968478]"></select>
<span class="field-validation-valid" data-valmsg-replace="true" data-valmsg-for="dropbox[4fb103e3-06e7-4c88-8836-73b855968478]"></span>
</span>
<div id="hiddenothertexbox"></div>
</div>
Javascript is as follows:
function getData(title, i) {
var value = title.options[title.selectedIndex].value;
var y = i.replace(/-/g, '')
$('#hiddenother').attr('id', y);
if (value == 'Other') {
str = '<label id="leftlabel">if other, please specify</label><span><input id="textboxid" class="text-box single-line" type="text" value="" name="textbox ></input></span>';
$('#'+y).html(str);
}
else {
str = '';
$('#'+y).html(str);
}
}
teh javascript gets the names of the dropbox and replaces the id of 'hiddenanothertextbox' with that id so its unique. I have an idea of the problem, i think its because when the user does not click teh first dropbox the id of 'hiddenanothertextbox' does not change for the first dropbox and when another dropbox is added and the value is changed, the hiddenanothertextbox for first dropox value changes adding it in front of first not second. I am struggling to achieve teh required result.
UPDATED JAVASCRIPt
function getData(title, i) {
var value = $(title).val();
var y = i.replace(/-/g, '');
$('#hiddenother').attr('id', y);
if (value == 'Other') {
str = '<label id="leftlabel">if other, please specify</label><span><input id="textboxid" class="text-box single-line" type="text" value="" name="textbox"" ></input></span>';
$(title).after(str);
}
else {
$(title).nextUntil('#textboxid').remove();
}
}
Working Demo
Use this code snippet.
var flag = 0;
function getData(title, i) {
var value = $(title).val();
var y = i.replace(/-/g, '');
$('#hiddenother').attr('id', y);
if (value == 'Other' ) {
if(flag == 0){
flag=1;
str = '<label id="leftlabel">if other, please specify</label><span><input id="textboxid" class="text-box single-line" type="text" value="" name="textbox"></input></span>';
$(title).after(str);
}
}
else {
flag=0;
$(title).nextUntil('#textboxid').remove();
}
}
Html :
<select id="frequency" onchange="getData(this, name)" name="dropbox[4fb103e3-06e7-4c88-8836-73b855968478]">
Changes :
var value = $(title).val() gives you the correct value
Use onchange="getData(this, name)" instead of onclick=".."
In variable str : name="textbox" did not have ending "
use .after() or .append() instead of .html()

Set validation dependent on other fields

I have a field called ReclaimTotalAmount that displays a value from a c# model.
<div class="container-left">
Reclaim Total: <span data-bind='text: model.ReclaimTotalAmount'></span>
</div>
And I also have a field that displays the value of the Sum of fields:
<div class="container-left">
Countered Total:<span data-bind='text: model.CounteredTotalAmount'></span>
</div>
To get the CounteredTotalAmount I use the following
self.model.CounteredTotalAmount = ko.computed(function () {
var SumCounterTotals = 0;
for (var i = 0; i < self.model.CounterReclaimViewModels().length; i++) {
SumCounterTotals += (
parseFloat(self.model.CounterReclaimViewModels()[i].CounteredTimeAmount())
+ parseFloat(self.model.CounterReclaimViewModels()[i].CounteredMileAmount())
+ parseFloat(self.model.CounterReclaimViewModels()[i].CounteredAppurtenanceAmount())
)
}
So I need to check weather the Countered total is greater than the ReclaimTotal. I tried this:
I created an extension
self.model.CounteredTotalAmount.extend({
greaterThan: { params: self.model.ReclaimTotalAmount, message: "Car number high must be greater than the low." }
});
then this is the function
ko.validation.rules['greaterThan'] = {
validator: function (val, other) {
if (val != null && val != "" && other != null) {
var first = parseInt(val);
var second = parseInt(ko.unwrap(other));
if (!isNaN(first) && !isNaN(second)) {
return first > second;
}
}
return true;
},
message: 'Must be greater than or equal to the other value'
};
everything works except the validation. I am not able to generate an error message if the Countered Total is greater than the Reclaim total...
Thanks
Multiple things could go wrong, but because you haven't' posted a complete example only code fragments you need to check the following things:
Because you are creating a custom validator you need to call ko.validation.registerExtenders(); before you want to use it for the first time.
the KO .extend({ }) returns the extended observable so you need to override the existing property with the result:
self.CounteredTotalAmount = self.CounteredTotalAmount.extend({
greaterThan: {
params: self.ReclaimTotalAmount,
message: "Car number high must be greater than the low."
}
});
Because KO validation only overrides the value and checked binding to automatically display the error message. So you need to use the validationMessage binding to display your error because you are using the text binding here:
<div class="container-left">
Countered Total:<span data-bind='text: CounteredTotalAmount'></span>
<span data-bind="validationMessage: CounteredTotalAmount"></span>
</div>
Here is a working JSFiddle with the simplified version of your code.

Serialize HTML Form in JavaScript and then Convert to a .NET Type in C#

I'm trying to take a HTML form and serialize the fields so that it can be stored as attributes against an element in JavaScript (you can use jQuery). This can later be parsed in C# and converted to a .NET type. This must work for any type as the form is generated via an Ajax call to the server.
For example given the following form:
<form>
<input type="text" name="Assembly" value="MyAssembly.dll" />
<input type="text" name="Class" value="MyClass" />
<input type="text" name="Parameters.Parameter1" value="5" />
<input type="text" name="Parameters.Parameter2" value="10" />
</form>
It would produce something like:
<widget assembly="MyAssembly.dll" class="MyClass" parameters="???"></widget>
Note: ??? would be replaced with either JSON or XML (depending on your which you think is best).
Now say I stored this string in the database I need to parse it on the server to convert it to a .NET type. I can do a regular expression to get the appropriate attributes leaving me with the following variables:
var assembly = "MyAssembly.dll";
var #class = "MyClass";
var parameters = "???";
Now finally I need to serialize this to a .NET type.
I'd appreciate it if someone could help. Thanks
I've come up with something that works. My solution is slightly more complicated but I'll try to post the key bits in case anyone is interested.
First I created the following plugins:
$.fn.serializeObject = function(prefix) {
var o = {};
// Serialize the form as an array
var a = this.serializeArray()
.filter($.proxy(function(element) {
// Make sure the prefix matches and it is not a checkbox (this is needed since ASP.NET MVC renders a hidden checkbox for the false value)
return element.name.indexOf(prefix || '') == 0 && $('[name=\'' + element.name + '\'][type=\'checkbox\']', this).length == 0;
}, this));
// Now append the checkbox values (this makes sure we only have one element in the array with the correct value whether it is selected or not)
a = a.concat($('input[type=\'checkbox\']', this).map(function() {
return { 'name': this.name, 'value': $(this).is(':checked') ? 'true' : 'false' }
}).get());
$.each(a, function() {
var n = this.name.substr((prefix || '').length);
if (o[n] !== undefined) {
if (!o[n].push)
o[n] = [o[n]];
o[n].push(this.value || '');
} else
o[n] = this.value || '';
});
return o;
};
Now for my application I actually have a WYSIWYG plugin which embeds my custom widget tag within the editor. Here's an example of what you could do to create the widget tag from the form when it is submitted (this would then be stored in the database):
$('form').submit(function(e) {
var parameters = JSON.stringify($('form').serializeObject('Parameters.'));
var widget = '<widget assembly="' + $('[name=\'Assembly\']').val() + '" class="' + $('[name=\'Class\']').val() + '" parameters="' + parameters + '"></widget>';
...
});
Finally on the server you need to replace the widget on display by doing something like:
output = Regex.Replace(output, #"<widget assembly=""(.*?)"" class=""(.*?)"" parameters=""(.*?)""></widget>", m => ReplaceWidget(m, helper));
Here's the ReplaceWidget method:
private static string ReplaceWidget(Match match, HtmlHelper helper) {
var assembly = match.Groups[1].Value;
var #class = match.Groups[2].Value;
var serializedParameters = match.Groups[3].Value;
// Get the type
var type = Assembly.LoadFrom(HttpContext.Current.Server.MapPath("~/bin/" + assembly)).GetType(#class);
// Deserialize the parameters
var parameters = JsonConvert.DeserializeObject(HttpUtility.HtmlDecode(serializedParameters), type);
// Return the widget
return helper.Action("Widget", "Widgets", new { parameters = parameters }).ToString();
}
Hope this helps.

Categories

Resources