I have a Kendo Html.Kendo().ComboBox() inside script tag in asp.net mvc.
var input = '#(Html.Kendo().ComboBox()
.Name(Html.NameFor(model => model.AttributeUnitValue).ToString())
.DataTextField("Description")
.DataValueField("CodeLovId")
.DataSource(datasource => datasource
.Read(read => read
.Action("GetCodesList", "LookupCode", new { area = "Core", codeType = unitCodeType, selectedValue = minAccValue })
.Type(HttpVerbs.Post)
)
).HtmlAttributes(new { style = "width:50%" }))'
Out side this input control I have two variables unitCodeType and minAccValue, which I am not able to access in Action() in the given code. They are showing error. Please check below screen shot
How can I fix this ?
You can pass server-side variables to the Action() method of the HtmlHelper. The Html helper is evaluated on the server i.e. based on the fluent configuration an initialization script is created and output along with an element used for the initialization of the component. So the JavaScript variable you are trying to pass is not available in the context when the Html Helper is evaluated.
You have two options - use server-side variables or initialize the ComboBox using JS:
#{
var someParam = 3;
}
<label for="products">HtmlHelper:</label>
#(Html.Kendo().ComboBox()
.Name("products")
.DataTextField("ProductName")
.DataValueField("ProductID")
.DataSource(source =>
{
source.Read(read =>
{
read.Action("RemoteDataSource_GetProducts", "DropDownList",new { myParam = #someParam});
});
})
.HtmlAttributes(new { style = "width: 200px;" })
)
<label for="products">JS initialization:</label>
<input id="products_js" style="width:200px;"/>
<script>
var someOtherParam = "test";
$("#products_js").kendoComboBox({
dataTextField: "ProductName",
dataValueField: "ProductID",
dataSource: {
transport: {
read: {
dataType: "jsonp",
url: "https://demos.telerik.com/kendo-ui/service/Products",
data:{
myOtherParam:someOtherParam
}
}
}
}
});
If you inspect the Network tab in this example you will see the different parameters passed to the read endpoint.
Related
I am using bellow code to insert the data to db. While Clicking the save button the data should be bind to the model and needs to be posted to controller action . But the data is not bind to the model. What is the issue in the bellow code . Any please help me to solve the below issue.
#(Html.Kendo().TextBoxFor(model => model.Code)
.HtmlAttributes(new { placeholder = "Enter Code", required = "required",
validationmessage="Code is Required" })
)
<input type="button" title="Save" id="btnsave" value="Save" onclick="submit()"/>
<script>
function submit(data) {
debugger;
console.log("Cosoledata "+JSON.stringify(data))
$.ajax({
type: "POST",
url: '#Url.Action("action", "controller")',
data: { data: #Model },
dataType: "json",
success: function (response) {
}
});
}
</script>
data: { data: #Model },
In the JavaScript script, you can directly get the Model data via the #Model.
To send the model data to the controller method, you could create a JavaScript object, then use JQuery to get the related property value (such as Code), then send the object to the controller method.
Please refer the following sample:
View page:
#section Scripts {
#{await Html.RenderPartialAsync("_ValidationScriptsPartial");}
<script>
$(function () {
$("#btnCreate").click(function () {
var review = {}; //create a JavaScript Object.
//user JQuery to get the entered value, and set the property value.
review.ReviewID = $("#ReviewID").val();
review.MovieID = $("#MovieID").val();
review.goreRating = $("#goreRating").val();
review.shockRating = $("#shockRating").val();
review.jumpRating = $("#jumpRating").val();
review.plotRating = $("#plotRating").val();
review.supernaturalRating = $("#supernaturalRating").val();
review.starRating = $("#starRating").val();
//if you want to send multiple objects, you could create an array.
//var reviewlist = [];
//reviewlist.push(review);
$.ajax({
url: "/Home/AddReview",
method: "Post",
data: { "reviewViewModel": review } , // { "reviewViewModel": reviewlist },
success: function (response) {
alert(response);
},
error: function (response) {
console.log("error");
}
})
});
})
</script>
}
Controller method:
[HttpPost]
public IActionResult AddReview(ReviewViewModel reviewViewModel)
{
if (ModelState.IsValid)
{
//do something
}
return View();
}
The result as below:
I am trying to make the helper #Html.EnumDropDownListFor searchable with an input tag on it. That way I can type to search for an item in the huge list. I preferably want to make this hard coded without other plugins. Can someone help me?
Here is the code:
<div>Escolha aqui o banco de sua preferĂȘncia:</div>
#Html.EnumDropDownListFor(model => model.BankPaymentMethods, " ", htmlAttributes: new {#class = "form-control"})
The EnumDropDownListFor helper only generates <select> elements. The closest you can get without a plugin would be an input with a datalist and the list attribute.
Assuming your enum is called BankPaymentMethod and BankPaymentMethods is an IEnumerable of some sort, and your model has a PaymentMethod property:
#Html.TextBoxFor(m => m.PaymentMethod, new { #class = "form-control", list = "payment-methods" })
<datalist id="payment-methods">
#foreach(var method in Model.BankPaymentMethods)
{
<option value="#method">#method</option>
}
</datalist>
For reference: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/datalist.
Typically its done inside a text box, I guess you can do it inside a Select by appending the value and name also you need to paste your VM or selectList VMModel. I have made some assumptions, code is not tested, but with a couple change and hopefully it will help you.
#Html.TextBoxFor(model => model.BankPaymentID)
#section scripts{
// you can update to the latest version of Jquery-ui, I put in the most compatible version for you
<script src="~/Scripts/jquery-ui-1.15.1.js">script>
<link rel="stylesheet" href="http://code.jquery.com/ui/1.15.1/themes/base/jquery-ui.css">
<script>
$(function () {
$("#BankPaymentID").autocomplete({
source: function (request, response) {
$.ajax({
url: '#Url.Action("Searchable")', // server action
datatype: "json",
data: {
term: request.term // this what you are searching
},
success: function (data) {
response($.map(data, function (val, item) {
return {
label: val.Name,
value: val.Name,
BankPaymentID: val.ID
}
}))
}
})
},
select: function (event, ui) {
$.get("/Home/GetBankPaymentMethods", { BankPaymentID: ui.item.BankPaymentID }, function (data) {
$("#PaymentID").empty();
$.each(data, function (index, row) {
$("#PaymentID").append("<option value='" + row.PaymentID + "'>" + row.PaymentName + "option>")
});
});
}
})
})
script>
}
Controller Searchable Action
public ActionResult Searchable(string term)
{
if (!String.IsNullOrEmpty(term))
{
var list = db.banks.Where(c=>c.PaymentName.ToUpper().Contains(term.ToUpper())).Select(c => new { Name = c.PaymentName, ID = c.BankPaymentID })
.ToList();
return Json(list, JsonRequestBehavior.AllowGet);
}
else
{
var list = db.banks.Select(c => new { Name = c.PaymentName, ID = c.BankPaymentID })
.ToList();
return Json(list, JsonRequestBehavior.AllowGet);
}
}
Screen
Code
In this screen, we have used kendo treelist. I need to implement autocomplete dropdown in CODE column. How can i do that?
Try this
var ac = Html.Kendo()
.AutoComplete()
.Name("CodeAutoComplete")
.DataSource(ds =>
{
ds.Read(read =>
{
read.Url("youraction");
});
ds.ServerFiltering(true);
});
var treeGrid = Html.Kendo()
.TreeList<YourModel>()
.Name("SomeTreeList")
.Columns(columns =>
{
columns.Add().Field(t => t.YourProperty).Editor(ac.ToHtmlString());
});
I solve my above problem as per given below jquery code.
var input2 = jQuery('<input id="WEIGHT_UOM" value="' + e.model.WEIGHT_UOM + '">');
input2.appendTo($(".k-grid-edit-row").find("[data-container-for='WEIGHT_UOM']"))
//create AutoComplete UI component
$("#WEIGHT_UOM").kendoAutoComplete({
dataTextField: "ProjectDesc",
// template: '${ data.ProjectDesc }' + '<span style="display:none;> ${ data.ProjectDesc }</span>',
select: function (org1) {
var dataItem1 = this.dataItem(org1.item.index());
// model.set("field1", dataItem.field1);
e.model.set("WEIGHT_UOM", dataItem1.ProjectID);
},
dataSource: {
type: "jsonp",
serverFiltering: true,
transport: {
read: "#Url.Action("GetISOUnitAutoComp",
"DashBoard")",
}
}
});
I have somewhat of a complex requirement here (a real head-scratcher)... and I'm not sure on the best way to proceed:
Requirement:
Build a page for managing widgets (CMS content blocks) in MVC5 using AngularJS for the frontend (as per the rest of the admin UI). The problem is that each widget has its own specific set of properties. They all share some properties like Title, IsEnabled, etc.. but an HTML Widget for example will have a BodyContent field and a Slider Widget would have a collection of images, etc..
My first thought was using [UIHint] and Html.EditorFor so that each widget type will have its own markup.. I think that's pretty straightforward, but how could we get the properties from any such arbitrary widget into the AngularJS model?
Example Controller
widgetsApp.controller('widgetController', function ($scope, $http) {
$scope.emptyGuid = '00000000-0000-0000-0000-000000000000';
$scope.id = $scope.emptyGuid;
$scope.title = '';
$scope.order = 0;
$scope.enabled = false;
$scope.widgetType = '';
$scope.zoneId = $scope.emptyGuid;
// etc
// how to get properties of ANY widget type?
Is this even possible? Is there a better solution? Note, I might consider changing the code to use Knockout or some other such framework if it can support my requirements.
Edit
Note that the issue is further complicated because of the fact of needing to then pass such a model back to the server and dealing with it there. In regular MVC controllers, I can use Request.Form to inspect what other values are there, but I'm using Web API and not sure if that's possible there.
Edit 2
Okay, so I think I'm on the right track, but still having issues. Firstly, here's my progress:
I found out about .factory and made a test page like this:
<div ng-app="myApp">
<div ng-controller="controller1">
<button class="btn btn-primary" ng-click="showAllInfo()">Show Info</button>
</div>
<div ng-controller="controller2">
</div>
</div>
<script type="text/javascript">
var myApp = angular.module('myApp', []);
myApp.factory('widgetModel', function () {
return {
id: '00000000-0000-0000-0000-000000000000',
title: '',
order: 0,
enabled: false,
widgetName: '',
widgetType: '',
zoneId: '00000000-0000-0000-0000-000000000000',
displayCondition: '',
widgetValues: '',
pageId: null,
cultureCode: '',
refId: null,
};
});
// This is representative of the main controller
myApp.controller('controller1', function ($scope, widgetModel) {
$scope.emptyGuid = '00000000-0000-0000-0000-000000000000';
$scope.model = widgetModel;
$scope.model.id = $scope.emptyGuid;
$scope.showAllInfo = function () {
alert("id: " + $scope.model.id + ", New Property: " + $scope.model.myNewProperty);
};
});
// This is representative of the details controller (to add properties specific to that particular widget type)
myApp.controller('controller2', function ($scope, widgetModel) {
$scope.model = widgetModel;
$scope.model.myNewProperty = "My Awesome Widget";
});
</script>
The above test works beautifully.. however, when I use this sort of code in my real application it fails to work and the reason I believe is because the second controller is injected into the DOM later on.. here's what's happening:
I have a div as follows
<div ng-bind-html="widgetDetails"></div>
and after loading the other details, I load the html for this as such:
$http.get("/admin/widgets/get-editor-ui/" + $scope.model.id).success(function (json) {
$scope.widgetDetails = $sce.trustAsHtml(json.Content);
});
That works.. I can see my the html controls for my new properties there.. the following snippet is the HTML which is injected into the above div:
<div ng-controller="widgetDetailsController">
<div class="col-sm-12 col-md-12">
<div class="form-group">
#Html.Label("BodyContent", "Body Content", new { #class = "control-label" })
#Html.TextArea("BodyContent", null, new { #class = "form-control", ng_model = "model.bodyContent", ui_tinymce = "tinyMCEOptions_BodyContent" })
</div>
</div>
<button class="btn" ng-click="test()">Test</button>
</div>
<script type="text/javascript">
widgetsApp.controller('widgetDetailsController', function ($scope, $http, widgetModel) {
$scope.model = widgetModel;
$scope.json = angular.fromJson($scope.model.widgetValues);
$scope.model.bodyContent = $scope.json.bodyContent || "";
$scope.test = function () {
alert($scope.model.bodyContent);
};
});
</script>
When I click, the "Test" button, nothing happens...
I tried to load a controller dynamically via the method outlined at this link: http://www.bennadel.com/blog/2553-loading-angularjs-components-after-your-application-has-been-bootstrapped.htm
It doesn't work. To be honest though, I am new to AngularJS and don't really know all the ins out outs of it.. any help would be great.
IF you are just looking to get the properties and their values, then on AngularJS or Javascript side you can just iterate over the object properties to get all the properties defined over the object.
for(var key in obj){
$scope[key]=obj[key];
}
Once on scope you can bind it to the view using ng-model.
This approach would get you the data but metadata about the data such as control to render for property need would not work.
For advance scenarios you should try to send metadata about each properties that can help render it on the view.
If ng-model is setup correctly all data would be send to server.
On the server you can use the dynamic keyword as input parameter to webapi method and there should be a similar method to iterate over the payload using key value pair.
I ended up changing to KnockoutJS, partly because AngularJS ended up being a bit overkill for my needs, but also because it couldn't handle this situation very nicely (or at least there was no obvious and clean way to do it). My KnockoutJS solution is below:
In the main page, I add an html element:
<fieldset id="widget-details"></fieldset>
An example of arbitrary HTML to be injected:
<div id="widget-content" class="col-sm-12 col-md-12">
<div class="form-group">
#Html.Label("BodyContent", "Body Content", new { #class = "control-label" })
#Html.TextArea("BodyContent", null, new { #class = "form-control", data_bind = "wysiwyg: bodyContent, wysiwygConfig: tinyMCEConfig" })
</div>
</div>
<script type="text/javascript">
function updateModel() {
var data = ko.mapping.fromJSON(viewModel.widgetValues());
viewModel.bodyContent = ko.observable("");
if (data && data.BodyContent) {
viewModel.bodyContent(data.BodyContent());
}
viewModel.tinyMCEConfig = {
theme: "modern",
plugins: [
"advlist autolink lists link image charmap print preview hr anchor pagebreak",
"searchreplace wordcount visualblocks visualchars code fullscreen",
"insertdatetime media nonbreaking save table contextmenu directionality",
"emoticons template paste textcolor"
],
toolbar1: "insertfile undo redo | styleselect | bold italic | alignleft aligncenter alignright alignjustify | bullist numlist outdent indent | link image",
toolbar2: "print preview media | forecolor backcolor emoticons",
image_advtab: true,
templates: [
{ title: 'Test template 1', content: 'Test 1' },
{ title: 'Test template 2', content: 'Test 2' }
],
content_css: tinyMCEContentCss
};
};
function onBeforeSave() {
var data = {
BodyContent: viewModel.bodyContent()
};
viewModel.widgetValues(ko.mapping.toJSON(data));
};
</script>
Then in my script for the main page, I use the following:
$.ajax({
url: "/admin/widgets/get-editor-ui/" + self.id(),
type: "GET",
dataType: "json",
async: false
})
.done(function (json) {
var result = $(json.Content);
var content = $(result.filter('#widget-content')[0]);
var details = $('<div>').append(content.clone()).html();
$("#widget-details").html(details);
var scripts = result.filter('script');
scripts.appendTo('body');
// ensure the function exists before calling it...
if (typeof updateModel == 'function') {
updateModel();
var elementToBind = $("#widget-details")[0];
ko.cleanNode(elementToBind);
ko.applyBindings(viewModel, elementToBind);
}
})
.fail(function () {
$.notify("There was an error when retrieving the record.", "error");
});
and when I save, I call this code:
// ensure the function exists before calling it...
if (typeof onBeforeSave == 'function') {
onBeforeSave();
}
Works really well.
So I was trying to bind a complex object , a list, to the detail grid of the the Kendo grid. I understand that you can not do that, so what I did was grab the data and turn it into a JSON and use that as a data source for this grid I created. The grid is created like this
#(Html.Kendo().Grid(Model).Name("Access")
.Columns(columns =>
{
columns.Bound("ProjId").Width(220).Title("Project #");
})
//I tried
.DetailTemplate("<div id=DetailTemplate'></div>")
// I also tried
.ClientDetailTemplateId("<div id=DetailTemplate'></div>")
.Selectable()
.Events(events => events.DetailInit("initDetailGrid"))
.DataSource(dataSource => dataSource
.Ajax()
.ServerOperation(false)
)
)
I then have this in my script
<script type="text/javascript">
function initDetailGrid(e) {
//Hide the grid header
$(".k-grid tbody .k-grid .k-grid-header").hide();
var grid = e.sender;
//Get the data from the selected record
var currentDataItem = grid.dataItem(grid.select());
var newJsonObject = [];
for (var i = 0; i < currentDataItem.taskId.length; i++) {
var taskId = currentDataItem.taskId[i];
newJsonObject.push({
Id: objId,
Interval: currentDataItem.InternalExternal[taskId],
....
});
}
$("#DetailTemplate").kendoGrid({
columns: [
{field:"taskId", template:..stuff..},
{field: "Interval", template: .. stuff..}
],
dataSource: newJsonObject
});
}
</script>
So basically I want to use the $("#DetailTemplate") as the detail grid for the row but it not working and I do not know how to approach it.
EDIT
What I am trying to do is create a Kendo UI grid, via javascript, to use as the detail template for the parent Grid, which is created using the ASP-MVC helper.
It is not getting clear what you are trying to achieve. Did you check the hierarchy demo here?
Basically all you need to replace inside of it is to fill the dataSource directly instead of using transport configuration.
function detailInit(e) {
$("<div/>").appendTo(e.detailCell).kendoGrid({
dataSource: {
//via the data option of the dataSource
data: e.data.NestedArrayFeild
},
scrollable: false,
sortable: true,
pageable: true,
columns: [
{ field: "OrderID", width: "70px" },
{ field: "ShipCountry", title:"Ship Country", width: "110px" },
{ field: "ShipAddress", title:"Ship Address" },
{ field: "ShipName", title: "Ship Name", width: "200px" }
]
});
}