Kendo DateTimePicker set value from json result - json

I have a big trouble with pasting a value in Kendo DateTimePicker inside Kendo Grid from json result. So I have two forms on page. In first I'm loading file:
#using (Html.BeginForm("GetImportSalesModelFromFile", "ExportImport", FormMethod.Post, new { id = "GetImportSaleModelFromFileForm", enctype = "multipart/form-data" }))
{
<input id="importFileInput" type="file" accept="text/csv" name="file" class="user-success" required>
<input style="width: 100px;" type="submit" value="Add">
}
On form submit called function
$('#GetImportSaleModelFromFileForm').submit(function(e) {
e.preventDefault();
var url = $(this).attr('action');
var xhr = new XMLHttpRequest();
var fd = new FormData();
fd.append("file", document.getElementById('importFileInput').files[0]);
xhr.open("POST", url, true);
xhr.send(fd);
xhr.addEventListener("load", function(event) {
AppendImportModel(JSON.parse(event.target.response));
}, false);
});
In controller I get needed import model
public ActionResult GetImportSalesModelFromFile(HttpPostedFileBase file)
{
var importModel = _importService.ConstructSaleImportModel(file.InputStream, file.ContentType);
return Json(importModel, JsonRequestBehavior.AllowGet);
}
In function AppendImportModel I parse result and paste it in kendo grid in second form
#(Html.Kendo().Grid<ImportSaleItemModel>().Name("ImportSalesGrid")
.DataSource(dataSource => dataSource.Ajax())
.Events(x => x.DataBound("initMenus"))
.Columns(columns =>
{
columns.Bound(x => x.Goods.PictureId)
.ClientTemplate("<img style='height: 50px;' src='" + Url.Action("Contents", "FileStorage", new { id = "#= Goods.PictureId #" }) + "'/>")
.Title("")
.Sortable(false)
.HtmlAttributes(new Dictionary<string, object> { { "style", "padding: 3px !important; height: 52px !important; width:52px !important;" } });
columns.Bound(x => x.Goods.Title)
.ClientTemplate("<a onclick='ShowInfoGoodWindow(#= Goods.Id #)'>#= Goods.Title #</a><br>" +
"<span><b>#= Goods.Article #</b> <descr>#= Goods.Description #</descr></span><br><input type='hidden' name='ImportedGoodList[#= index(data)#].Id' value='#= Goods.Id #' />")
.Title("Description");
columns.Bound(x => x.Price)
.ClientTemplate("<input class='priceEditor' maxlength='10' style='width:50px; text-align: center;' type='text' name='ImportedGoodList[#= index(data)#].Price' onkeypress='return isPriceKey(event)' oninput='$(this).get(0).setCustomValidity(clearValidation);' value='#=Price.ParsedValue #'>")
.HtmlAttributes(new Dictionary<string, object> { { "style", "text-align: center;" } })
.Title("Price");
columns.Bound(x => x.Discount)
.ClientTemplate("<input class='discountEditor' maxlength='10' style='width:50px; text-align: center;' type='text' name='ImportedGoodList[#= index(data)#].Discount' onkeypress='return isPriceKey(event)' oninput='$(this).get(0).setCustomValidity(clearValidation);' value='#=Discount.ParsedValue #'>")
.HtmlAttributes(new Dictionary<string, object> { { "style", "text-align: center;" } })
.Title("Discount");
columns.Bound(x => x.DepartmentId)
.HtmlAttributes(new { #class = "templateCell" })
.ClientTemplate(Html.Kendo().DropDownList().Name("Department#=LineId#").BindTo(Model.Departments).Value("#= DepartmentId #").ToClientTemplate().ToHtmlString())
.Title("Department");
columns.Bound(x => x.SaleDateTime)
.HtmlAttributes(new { #class = "templateCell" })
.ClientTemplate(Html.Kendo().DateTimePicker().Name("SaleDateTime#=LineId#").Value("#= ConvertedSaleDateTime #").ToClientTemplate().ToHtmlString())
.Title("Sale Date");
columns.Bound(x => x.SellerId)
.HtmlAttributes(new { #class = "templateCell" })
.ClientTemplate(Html.Kendo().DropDownList().Name("Seller#=LineId#").BindTo(Model.Sellers).Value("#= SellerId #").ToClientTemplate().ToHtmlString())
.Title("Seller");
columns.Bound(x => x.IsCashPayment)
.ClientTemplate("<input type='checkbox' id='IsCashPayment#=LineId#' checked='#= IsCashPayment.ParsedValue #' class='regular-checkbox'/><label for='IsCashPayment#=LineId#'></label> Yes")
.Title("Is Cash Payment");
})
)
In all columns using "#= value #" works fine but not in this line
.ClientTemplate(Html.Kendo().DateTimePicker().Name("SaleDateTime#=LineId#").Value("#= ConvertedSaleDateTime #").ToClientTemplate().ToHtmlString())
"#= ConvertedSaleDateTime #" not changed on real value, but if I write
.ClientTemplate("#= ConvertedSaleDateTime #")
I will get right value "10/07/2013 13:15". And if I write
.ClientTemplate(Html.Kendo().DateTimePicker().Name("SaleDateTime#=LineId#").Value("10/07/2013 13:15").ToClientTemplate().ToHtmlString())
I will get Kendo DateTimePicker inside grid with value "10/07/2013 13:15"
How I can set value to this DateTimePicker from ConvertedSaleDateTime?
Please, help me. Thanks in advance.

I solved my problem via jQuery. Maybe someone needs this solution or knows something more beautiful.
In client template of SaleDateTime columnt I wrote:
columns.Bound(x => x.SaleDateTime).ClientTemplate("<input class='saleDateTimeEditor' id='SaleDateTime#=index(data)#' name='ImportedSalesList[#=index(data)#].SaleDateTime' value='#= ConvertedSaleDateTime #'>")
And in DataBound event of my kendo grid I initialized all kendo DateTimePickers:
$('.saleDateTimeEditor').each(function () {
var id = $(this).attr('id');
var value = new Date(Date.parse($(this).val()));
$("#" + id).kendoDateTimePicker({
value: value,
max: new Date(Date.now())
});
$('#'+id).attr('readonly', 'readonly');
});
ConvertedSaleDateTime is in format "yyyy/MM/dd hh:mm:ss"

Related

How can show datepicker calendar in a row which are added newly

I am trying to show a datepicker calendar in each row of table . But it shows only first row. When I add new row in a table, the datepicker is not showed newly added rows.
Model class
[DataType(DataType.Date, ErrorMessage = "Date only")]
[DisplayFormat(DataFormatString = "{0:dd-MM-yyyy}", ApplyFormatInEditMode = true)]
public string FromDate { get; set; }
[DataType(DataType.Date, ErrorMessage = "Date only")]
[DisplayFormat(DataFormatString = "{0:dd-MM-yyyy}", ApplyFormatInEditMode = true)]
public string ToDate { get; set; }
Html file
<table>
<tbody>
<tr>
<td>#Html.TextBoxFor(model => model.FromDate, new { #class = "form-control" })</td>
<td>#Html.TextBoxFor(model => model.ToDate, new { #class = "form-control" })</td>
</tr>
</tbody>
</table>
<button type="button" id="btnUpdate" name="submitButton" value="DeleteAtt"
class="btn btn-primary form-control" onclick="AddNew();">
<i class="fa fa-save"></i><span class="padding-left-ten">Add New Row</span>
</button>
<script type="text/javascript">
$(document).ready(function () {
$("#FromDate").datepicker({ format: 'dd/mm/yyyy', todayHighlight: true, date: new Date(), autoclose: true, todayBtn: 'linked' });
$("#ToDate").datepicker({ format: 'dd/mm/yyyy', todayHighlight: true, date: new Date(), autoclose: true, todayBtn: 'linked' });
});
function AddNew() {
var clone = $("#tblEntry tr:last").clone().find('input').val('').end().insertAfter("#tblEntry tr:last");
}
</script>
First, you'll need to stop duplicating id values in your HTML. Those need to be unique across the DOM, otherwise your selectors will have no way to identify multiple elements with the same id. Instead, assign a class that you can recognize for the date inputs. For example:
<td>#Html.TextBoxFor(model => model.FromDate, new { #class = "form-control date-input" })</td>
#Html.TextBoxFor(model => model.ToDate, new { #class = "form-control date-input" })
Note the new "date-input" class values. Then use those to initialize the datepicker plugin:
$(document).ready(function () {
$(".date-input").datepicker({ format: 'dd/mm/yyyy', todayHighlight: true, date: new Date(), autoclose: true, todayBtn: 'linked' });
});
Second, it's important to understand that this will only initialize the datepicker plugin for elements which exist when this code executes, which is only once when the page loads. Any elements added afterward would also need to have the plugin initialized at that time. So you'd do that in your AddNew function:
function AddNew() {
var clone = $("#tblEntry tr:last").clone().find('input').val('').end().insertAfter("#tblEntry tr:last");
$(clone).find(".date-input").datepicker({ format: 'dd/mm/yyyy', todayHighlight: true, date: new Date(), autoclose: true, todayBtn: 'linked' });
}
If you like, you can reduce the repeated use of the datepicker plugin configuration by extracting that into its own function. Perhaps something like this:
function initDatepicker(selection) {
selection.datepicker({ format: 'dd/mm/yyyy', todayHighlight: true, date: new Date(), autoclose: true, todayBtn: 'linked' });
}
Then you'd call it in both places with your selected jQuery results:
$(document).ready(function () {
initDatepicker($(".date-input"));
});
and:
function AddNew() {
var clone = $("#tblEntry tr:last").clone().find('input').val('').end().insertAfter("#tblEntry tr:last");
initDatepicker($(clone).find(".date-input"));
}

Why does the value attribute render an input as read only and defaultValue render it as read-write?

So I have a cart in which the quantity of the items added are dynamically incremented by +1 every time you add the same item, and within the cart itself the quantity of an added item can be manually changed by any preferred user number.
If I use the value="" attribute in the input field, the value is dynamically updated correctly, but then doesn't allow me to manually change the value. And if I use defaultValue="" the value does not update correctly every time an item is added, but allows me to manually chnage the value as required.
How can I both show the dynamic value correctly and be able to update the value field as required? My code is as follows:
class CartItem2 extends Component {
constructor(props) {
super(props);
}
handleChange = e => {
const { name, type, value } = e.target;
const val = type === 'number' ? parseFloat(value) : value;
this.setState(() => { return { [name]: val }});
};
updateCartItem = async (e, updateCartItemMutation) => {
e.preventDefault();
console.log('Updating Cart Item!!');
console.log(this.state);
const res = await updateCartItemMutation({
variables: {
id: this.props.cartItem.id,
quantity: this.state.quantity,
},
});
console.log('Updated!!');
};
static getDerivedStateFromProps(nextProps, prevState){
if (nextProps.cartItem.quantity !== prevState.quantity) {
console.log("nextProps ", nextProps);
console.log("prevState", prevState);
return {quantity: nextProps.cartItem.quantity};
}
else return null;
}
render() {
const { cartItem, client } = this.props;
const { quantity } = this.state;
return (
<CartItemStyles>
<img width="100" src={cartItem.item.image} alt={cartItem.item.title} />
<div className="cart-item-details">
<h3>{cartItem.item.title}</h3>
<p>
{formatMoney(cartItem.item.price * cartItem.quantity)}
{' - '}
<em>
{cartItem.quantity} × {formatMoney(cartItem.item.price)} each
</em>
</p>
<Mutation
mutation={UPDATE_CART_ITEM_MUTATION}
variables={this.state}
>
{(updateCartItem, { loading, error }) => {
return (
<Form2 key={cartItem.id} onSubmit={e => this.updateCartItem(e, updateCartItem)}>
<Error error={error} />
<label htmlFor="quantity">
<input
type="number"
id="quantity"
name="quantity"
placeholder="Quantity"
required
value={quantity}
onChange={this.handleChange}
/>
</label>
<button type="submit">Updat{loading ? 'ing' : 'e'}</button>
</Form2>
)
}}
</Mutation>
</div>
<RemoveFromCart id={cartItem.id} />
</CartItemStyles>
);
}
}
If you go here: flamingo-next-production.herokuapp.com, login using testing123#123.com and testing123, then click shop, then click cart, then add to cart multiples of the same item, then go to the cart and try and manually alter the item value.
It looks like you are making a controlled input with a default value from the state? If so, you would need to set the initial quantity in the state to the cartItem.quantity value.
A lot of references are missing from below, but you should get the idea.
class CartItem extends Component {
constructor(props) {
super(props);
this.state = {
quantity: props.cartItem.quantity,
};
}
handleChange = e => {
const { name, type, value } = e.target;
const val = type === 'number' ? parseFloat(value) : value;
this.setState({ [name]: val });
};
render() {
const { quantity } = this.state;
return (
<Mutation
mutation={UPDATE_CART_ITEM_MUTATION}
variables={this.state}
>
{(updateCartItem, { loading, error }) => {
return (
<Form2 onSubmit={e => this.updateCartItem(e, updateCartItem)}>
<Error error={error} />
<label htmlFor="quantity">
<input
type="number"
id="quantity"
name="quantity"
placeholder="Quantity"
value={quantity}
onChange={this.handleChange}
required
/>
</label>
<button type="submit">Updat{loading ? 'ing' : 'e'}</button>
</Form2>
)
}}
</Mutation>
)
}
}
I think the problem is that you are passing a value from props carItem to defaultValue but onChange you are changing the state which is not passed to defaultValue.
To fix this you need to pass the state to defaultValue OR update the prop carItem in onChange
The issue was resolved by removing static getDerivedStateFromProps() and replacing with:
componentDidUpdate(prevProps, prevState) {
if (this.props.cartItem.quantity !== prevProps.cartItem.quantity) {
let quantity = this.props.cartItem.quantity;
this.setState(() => {
return {
quantity
}}
);
}
}
componentDidMount() {
let quantity = this.props.cartItem.quantity;
this.setState(() => {
return {
quantity
}}
);
}

disable textboxfor using a checkboxfor razor mvc and jquery

I am trying to disable/enable an #Html.TextBoxFor in razor using an #Html.CheckBoxFor
I have defined my CheckBoxFor in this manner:
#Html.CheckBoxFor(m => m.ResYearChecked, new { Name = "ResYearChecked", id = "ResYearChecked" })
#Html.TextBoxFor(m => m.SearchResYear, new { Name = "SearchResYear", id = "SearchResYear" })
and I am trying to call the script:
<script>
$('ResYearChecked').change(function () {
$("SearchResYear").prop("disabled", !$(this).is(':checked'));
});
</script>
Do I need to add the onclick attribute to the CheckBoxFor?
I was able to figure out the solution. I enabled the attribute readonly for the #Html.TextBoxFor. I then removed the readonly attribute once the #Html.CheckBoxFor was checked.
Here is the code for my #Html.CheckBoxFor and #Html.TextBoxFor
#Html.CheckBoxFor(m => m.ResYearChecked, new { Name = "ResYearChecked", id = "ResYearChecked" })
#Html.TextBoxFor(m => m.SearchResYear, new { Name = "SearchResYear", id = "SearchResYear", #readonly = "readonly" })
Here is the JavaScript
<script>
$('#ResYearChecked').change(function () {
if ($(this).is(":checked")) {
$("#SearchResYear").removeAttr("readonly");
$("#SearchResYear").focus();
} else {
$("#SearchResYear").attr("readonly", "readonly");
}
});
</script>

Vertical alignement within razor view

I have this snippet :
<p>
#Html.LabelFor(m => m.address, new { style="vertical-align: middle;" }) #Html.TextAreaFor(m => m.address, new { #class = "addition ", value = "",rows="4", required = "required" })
</p>
I get this result :
I need to put the label in the middle.
How can I change the code above to accomplish this task ?
add vertical-align:middle to text area too.
<p>
#Html.LabelFor(m => m.Address, new { style = "vertical-align: middle;" })
#Html.TextAreaFor(m => m.Address, new { #class = "addition ", style = "vertical-align: middle;", value = "", rows = "4", required = "required" })
</p>

Kendo DropDown filter and show in GridView

I have filter with dropdown cities. I wanna that when I choose city from dropdown lis and click button search to show data in gridview with this city.
First question
1) How to get value from dropdown and pass to button and call controller?
2) I tried without dropdown, when populate value directly in Read method but nothing, my gridview is empty.
This is my code
Partial View "Filter", View with gridview and method in controller that populate gridview.
#{
ViewBag.Title = "Filter";
}
<div class="filter-all">
<div class="filter-dropdown">
<div class="filter-part">
<div class="custom-label-div">
City:</div>
<div class="defaultSize">
#(Html.Kendo().DropDownList()
.Name("City")
.HtmlAttributes(new { style = "width:250px" })
.DataTextField("CityName")
.DataValueField("CityID")
.OptionLabel("...")
.DataSource(source =>
{
source.Read(read =>
{
read.Action("GetCities", "Filter");
});
})
)
</div>
</div>
</div>
<div class="filter-buttons">
<div class="button-filter-div">
<input type="button" value="Search City" onclick="location.href='#Url.Action("Index", "MFS3")'" class="k-button" style="width: 80px"/>
<input type="button" value="Cancel" onclick="location.href='#Url.Action("Index", "Preview")'" class="k-button" style="width: 80px"/>
</div>
</div>
</div>
#model IEnumerable<MFS_App.Models.MFS3ViewModel>
<div class="right-content shadow">
<div class="preview-header">
Preview Reports</div>
<div class="preview-content">
#Html.Partial("_Filter")
</div>
</div>
<div class="parent-preview-content shadow">
<div class="child-preview-content">
#Html.Partial("_ReportsGridView")
<div class="mfs-title">
<div class="filter-preview-div">
#(Html.Kendo().Grid(Model)
.Name("GridMFS3")
.Columns(columns =>
{
columns.Bound(p => p.FirstName).HtmlAttributes(new { style="width:50px"});
columns.Bound(p => p.LastName).HtmlAttributes(new { style ="width:70px"});
columns.Bound(p => p.Address).HtmlAttributes(new { style = "width:80px"});
columns.Bound(p => p.Mail).HtmlAttributes(new { style = "width:100px" });
columns.Bound(p => p.County).HtmlAttributes(new { style = "width:70px" });
columns.Bound(p => p.City).HtmlAttributes(new { style = "width:50px" }); columns.Command(c => c.Edit());
})
.DataSource(source =>
{
source.Server()
.Model(model => model.Id(m => m.MFS3_ID))
.Read(read => read.Action("GetMFS", "MFS3", new { cityID = 251} ))
.Update(update => update.Action("Update", "MFS3"));
})
.Editable(editable => editable.Mode(GridEditMode.PopUp))
.Selectable(selectable => selectable.Mode(GridSelectionMode.Multiple))
.Pageable()
.Resizable(resize => resize.Columns(true))
.HtmlAttributes(new { style = "width: 1850px" })
)
private IEnumerable<MFS3ViewModel> GetMFS3(int cityID)
{
return HelperClass.dbUp.TBL_MFS_MFS3_Input.Select(p => new MFS3ViewModel
{
CITYID = p.CITIYID,
MFS3_ID = p.MFS3_ID,
FirstName = p. FirstName,
LastName = p. LastName,
p.Address = p. p.Address,
.Mail = p. .Mail,
County = p. County,
City = p. City,
}).Where(p => p.CITYID == cityID);
}
I resolved this via jQuery and added parameter in my Index method
$('#btnSearch').click(function () {
var cityID = $("#City").data("kendoDropDownList").value();
document.location = "/MFS3/Index?cityId=" + cityID;
});
public ActionResult Index(int cityId)
{
return View(GetMFS3(cityId));
}