I have a ViewModel and a DropDownList with some values on my page:
public class MyViewModel
{
public string SelectedItemDrop1 { get; set; }
public string SelectedItemDrop2 { get; set; }
public string SelectedItemDrop3 { get; set; }
public List<OptionViewModel> Options { get; set; }
}
public class OptionViewModel
{
public string Number { get; set; }
public string Option { get; set; }
}
And, into my View:
#using (Html.BeginForm("Save", "Controller", FormMethod.Post))
{
<ul id="cursos">
<li>
#Html.DropDownListFor(c => c.SelectedItemDrop1,
new SelectList(Model.Options, "Number", "Option", Model.SelectedItemDrop1))
Choose 1
</li>
<li>
#Html.DropDownListFor(c => c.SelectedItemDrop2,
new SelectList(Model.Options, "Number", "Option", Model.SelectedItemDrop2))
Choose 2
</li>
<li>
#Html.DropDownListFor(c => c.SelectedItemDrop3,
new SelectList(Model.Options, "Number", "Option", Model.SelectedItemDrop3))
Choose 3
</li>
</ul>
}
When I use Javascript to change options from these select elements, my return is null. What's the problem? Thank you so much!!!
EDIT:
My javascript code:
$("#cursos li select").each(function (i, item) {
$(this).change(function () {
updateCursos($(this), 7);
});
$(this).blur(function () {
if ($(this).val() != -1) {
$(this).attr('disabled', 'disabled');
}
});
});
function updateCursos(select, avaiableCourses) {
var selecteds = '';
$("#cursos li select").each(function (i, item) {
var selected = $(item).val();
if (selected != -1)
selecteds += selected + ',';
});
var arr = selecteds.split(',');
$("#cursos li select").each(function (i, item) {
if ($(item).val() != select.val()) {
var oldValue = $(item).val();
if ($(item).val() == -1) {
var options = "<option value='-1'></option>";
for (i = 1; i <= avaiableCourses; ++i) {
if (select.val() != i && !contains(i, selecteds)) {
options += "<option value='" + i + "'>" + i + "ª option</option>";
}
}
options += "<option value='0'>Don't want it</option>";
$(item).children("option").remove();
$(item).html(options);
$(item).val(oldValue);
}
}
});
}
This way I'm sure that works, not even being javascript.
If the values are not being filled are coming from the database, with fixed values example: active, inactive, do the following
Create an enumerated type with these values
After the controller transforms this type enumerated in list using an internal class, turn it into a enumerable and go to the dropdownlist
example of usage:
# Html.DropDownListFor (model => model.chamados.UrgenciaId, new SelectList (ViewBag.urgencia, "Id", "Name"))
Related
What's the Blazor equivalent of this Knockout.js data-binding?
I can easily create a foreach loop through a C# List<T> object and bind to the object's properties however I'm struggling with this as the binding is for the id attributes.
HTML code:
<div data-bind="foreach : combinedArr">
<div data-bind="with: $data.recordCo">
<table id="tableFull">
<tbody>
<tr>
<td class="fixed-width iconCol" data-bind="with: $parent.targetCo">
<button data-bind="attr: { 'data-target': $data[0].tableTargetID, id: $data[0].buttonID }" data-toggle="collapse" type="button" onclick="glyphChanger(this.id)" class="btn btn-default iconButton glyphicon glyphicon-chevron-right" aria-label="Left Align" aria-hidden="true"></button>
</td>
</tr>
</tbody>
</table>
</div>
<div class="tbAdj panel panel-collapse collapse" data-bind="attr: { id: $data.countCo }">
<table class="table table-condensed tableSize tableSpacer" id="tableFull">
<tbody data-bind="foreach: $data.jsonCo">
....
</tbody>
</table>
</div>
</div>
Javascript code:
self.combinedArr = ko.observableArray();
self.post = function () {
voidNotification = false;
self.combinedArr.removeAll();
$.post(this.api + "/tabular", {
value: this.logSource()
}).success(
function (d) {
var counter = 0;
$.each(d, function (i, o) {
var objArr = JSON.parse(o);
//Parse a second time to access the objects individually
var recordParsed = JSON.parse(objArr[0]);
var jsonParsed = JSON.parse(objArr[1]);
//Data to populate the expandable table
jsArr = [];
for (var x in jsonParsed) {
jsArr.push({ jfieldName: jsonParsed[x].Name, jfieldValue: jsonParsed[x].Value });
}
//ID for the button that expands and collapses the table
var buttonID = "btUniqID" + counter;
//The id of the table - needs to be in the same array as the buttonID
var tableTargetID = "#jsonTable" + counter;
var idArr = [];
idArr.push({ tableTargetID: tableTargetID, buttonID: buttonID });
//The id for that table that needs to be on its own
var uniqueTableID = "jsonTable" + counter;
//Combine all the data and push to the combinedArr
self.combinedArr.push({ recordCo: recordParsed, jsonCo: jsArr, countCo: uniqueTableID, targetCo: idArr });
//Incremented for unique button ids
counter++;
});
if (counter === 0) {
self.FaultFound(true);
self.FaultText("Data could not be parsed");
$("#recordTable").css("display", "none");
} else {
self.FaultFound(false);
//Check if transaction is void
VoidHandler();
//Hides the loading animation
self.ShowDetailsLoading(false);
//Show the recordsTable
$("#recordTable").css("display", "block");
}
})
.error(
function (d) {
alert('failed ' + d);
}
);
}
I've created a C# class equivalent to self.combinedArr with the rows variable below:
public List<CombinedRow> rows = new List<CombinedRow>();
private async Task OnParseClicked()
{
try
{
var response = await Http.PostAsJsonAsync("api/TLogParser/Records", new TLogMessageRequestDto(logMessage: inputMessage));
parsedMessage = await response.Content.ReadFromJsonAsync<IEnumerable<RecordItem>>();
var jsArray = new List<Record>();
foreach (var m in parsedMessage)
{
jsArray.Add(new Record { jfieldName = m.MessageId, jfieldValue = m.RecordBody });
}
var counter = 0;
foreach (var m in parsedMessage)
{
//ID for the button that expands and collapses the table
var buttonID = "btUniqID" + counter;
//The id of the table - needs to be in the same array as the buttonID
var tableTargetID = "#jsonTable" + counter;
var row = new Row() { ButtonId = buttonID, TableTargetId = tableTargetID };
//The id for that table that needs to be on its own
var uniqueTableID = "jsonTable" + counter;
var combinedRow = new CombinedRow { recordCo = m, JsonCo = jsArray, CountCo = uniqueTableID, TargetCo = row};
rows.Add(combinedRow);
counter++;
}
}
catch (Exception e)
{
Console.WriteLine(e);
}
}
public class CombinedRow
{
public RecordItem recordCo { get; set; }
public Row TargetCo { get; set; }
public string CountCo { get; set; }
public List<Record> JsonCo { get; set; }
}
public class Row
{
public string ButtonId { get; set; }
public string TableTargetId { get; set; }
}
public class Record
{
public string jfieldName { get; set; }
public string jfieldValue { get; set; }
}
However, I'm not sure on the HTML/Blazor binding part of how to bind to the id attributes.
I have a problem with using #Html.DropDownListFor element.
What i have:
Model 'DatabaseModel':
public class DirectionEntity
{
public string Id { get; set; }
public string DirectionName { get; set; }
}
public class ViewModel
{
public int SelectedDirectionID { get; set; }
public List<DirectionEntity> DirectionList { get; set; }
}
Model 'DataFactory':
public class DataFactory
{
public static ViewModel Refresh()
{
using (var db = new MyDatabase())
{
return new ViewModel()
{
DirectionList = db.Directions.Select(_ => new { _.Id, _.DirectionName })
.ToList()
.Select(_ => new DirectionEntity() { Id = _.Id.ToString(), DirectionName = _.DirectionName })
.ToList(),
};
}
}
}
Controller:
public System.Web.Mvc.ActionResult AddNewDocument()
{
var db = DataFactory.Refresh();
return View(db);
}
[HttpPost]
public System.Web.Mvc.ActionResult AddNewEntry(ViewModel m)
{
m = DataFactory.Save(m);
ModelState.Clear();
return View(<some view>);
}
View:
#using (Html.BeginForm())
{
#Html.DropDownListFor(m => m.SelectedDirectionID, new SelectList(Model.DirectionList.Select(x => new SelectListItem { Value = x.Id.ToString(), Text = x.DirectionName }), "Value", "Text"), new { #class = "Duration", required = "required" })
<button type="submit" class="btn btn-default SaveAll">Save</button>
}
The question:
How to handle 'SelectedDirectionID' value, after user selected some position on dropdownlist, but not yet sent the request to the server using a POST-method.
See what the id of your dropdown is and then you can subscribe to the change event on the client side. You can do this using jQuery.
$("#idOfYourDropDown").change(function () {
// Do whatever you need to do here
// Here are some ways you can get certain things
var end = this.value;
var selectedText = $(this).find("option:selected").text();
var selectedValue = $(this).val();
alert("Selected Text: " + selectedText + " Value: " + selectedValue);
});
Also you should see my answer here on why you should not return a view from a POST action the way you are.
In this case you have to use Jquery. As per your view id for your drop down is 'SelectedDirectionID';
Your Js:
$(document).ready(function () {
var selectedValue = $('#SelectedDirectionID').val();
var selectedText = $("#SelectedDirectionID option:selected").text();
});
Or Inside drop down change event.
$('#SelectedDirectionID').change(function () {
var selectedValue = $(this).val();
var selectedText = $(this).find("option:selected").text();
});
I am trying to pass a model to the controller using an ajax post, but every time I do so, the model is null and I lose all the data I am trying to persist.
The ajax call:
$('#next').click(function (e) {
e.preventDefault();
var url = '#Url.Action("Manage")'
var _model = JSON.stringify(#Html.Raw(Json.Encode(Model)));
var _page = #(Model.pager.CurrentPage + 1);
$.ajax({
type: "POST",
contentType: "application/json; charset=utf-8",
url: url,
data: JSON.stringify({ 'model': _model, 'page': _page }),
success: function(result) {
console.log(result);
}
});
});
When I look at the serialized object, it looks like a correctly formatted JSON object with no errors thrown in the developer console.
The link that is triggering this jQuery call is just a basic action link:
#Html.ActionLink(">", "Manage", "Announcements", null, new { id = "next" })
My model is a little more complicated...
public class ManageViewModel : IEnumerable<EditViewModel>
{
[Display(Name="Start Date")]
[DataType(DataType.DateTime)]
public DateTime? StartDate { get; set; }
[Display(Name="End Date")]
[DataType(DataType.DateTime)]
public DateTime? EndDate { get; set; }
public string SearchString { get; set; }
public Pager pager { get; set; }
public List<EditViewModel> Data { get; set; }
public List<CategoryViewModel> Categories { get; set; }
public ManageViewModel()
{
Data = new List<EditViewModel>();
Categories = new List<CategoryViewModel>();
}
public IEnumerator<EditViewModel> GetEnumerator()
{
return Data.GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
return Data.GetEnumerator();
}
}
public class Pager
{
public int TotalItems { get; private set; }
public int CurrentPage { get; private set; }
public int PageSize { get; private set; }
public int TotalPages { get; private set; }
public int StartPage { get; private set; }
public int EndPage { get; private set; }
public Pager(int totalItems, int? page, int pageSize = 10)
{
int totalPages = (int)Math.Ceiling((decimal)totalItems / (decimal)pageSize);
int currentPage = page ?? 1;
int startPage = currentPage - 5;
int endPage = currentPage + 4;
if(startPage <= 0)
{
endPage -= (startPage - 1);
startPage = 1;
}
if(endPage > totalPages)
{
endPage = totalPages;
if(endPage > 10)
{
startPage = endPage - 9;
}
}
TotalItems = totalItems;
TotalPages = totalPages;
CurrentPage = currentPage;
PageSize = pageSize;
EndPage = endPage;
StartPage = startPage;
}
}
I can't convert the links in to a form because that breaks the pagination. Or maybe I'm just not understanding the full picture here.
Here is the section of the View where the pagination is occurring
if (Model.pager.EndPage > 1)
{
<div style="color:#337AB7; padding-bottom: 0px;">Page #Model.pager.CurrentPage of #Model.pager.TotalPages</div>
<ul class="pagination">
#if (Model.pager.CurrentPage > 1)
{
<li>
#Html.ActionLink("<<", "Manage", new { model = Model, start = Model.StartDate, end = Model.EndDate, query = Model.SearchString }, null)
</li>
<li>
#Html.ActionLink("<", "Manage", new { model = Model, page = Model.pager.CurrentPage - 1, start = Model.StartDate, end = Model.EndDate, query = Model.SearchString }, null)
</li>
}
#for (var _page = Model.pager.StartPage; _page < Model.pager.EndPage + 1; _page++)
{
<li class="#(_page == Model.pager.CurrentPage ? "active" : "")">
#Html.ActionLink(_page.ToString(), "Manage", new { model = Model, page = _page, start = Model.StartDate, end = Model.EndDate, query = Model.SearchString }, null)
</li>
}
#if (Model.pager.CurrentPage < Model.pager.TotalPages)
{
<li>
#Html.ActionLink(">", "Manage", "Announcements", null, new { id = "next" })
</li>
<li>
#Html.ActionLink(">>", "Manage", new { model = Model, page = Model.pager.TotalPages, start = Model.StartDate, end = Model.EndDate, query = Model.SearchString }, null)
</li>
}
</ul>
}
The action links attempting to pass the model, obviously don't work but I left them because I am focusing on getting one to work, the one listed previously, before getting all the others configured.
I have looked at the following SO posts and have had no luck with them:
Post an MVC model with AJAX?
Model properties null on Ajax post from list box change event
How to send a model in jQuery $.ajax() post request to MVC controller method
Pass Model To Controller using Jquery/Ajax
How to pass model in ajax post request?
Any ideas on how I might be able to do this? I need the model data to persist for searching/filtering which is done through a form. Thank you in advance for taking a look and giving your insights!
You need to include a parameterless constructor for your models. From the screenshot you have sent it seems there isn't a parameterless constructor for public Pager model.
I'm trying to draw my website map as follows
<ul>
<li>Cat1</li>
<li>Cat2
<ul class='sub2'>
<li>Cat21</li>
<li>Cat22</li>
<li>Cat23
<ul class='sub23'>
<li>Cat231</li>
<li>Cat232</li>
<li>Cat233
<ul class='sub233'>
<li>Cat2331</li>
<li>Cat2332</li>
<li>Cat2333</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
<li>Cat3
<ul class='sub3'>
<li>Cat31</li>
<li>Cat32</li>
<li>Cat33</li>
</ul>
</li>
<li>Cat4</li>
</ul>
The map provider is a List of PostCategory objects
List<PostCategory> MapProvider=new List<PostCategory>();
///....MapProvider.add(...);
CategoryMapViewModel siteMap=new CategoryMapViewModel(MapProvider);
var map=siteMap.Map.ToString();
and the PostCategory object
public class PostCategory{
[Key]
public int? CategoryId{get;set;}
[StringLength(20/*50*/,MinimumLength=3)]
public string Name{get;set;}
[StringLength(250)]
public string Description { get; set; }
//relationship
public int? IdPostCategoryParent { get; set; }
}
I have written some thing but it doesn't work recursively for subcategories of the subcategories: for example: it works for sub2 but not for sub23, sub332, sub....
here is my CategoryMapViewModel class
public class CategoryMapViewModel
{
public HtmlString Map { get; private set; }
private List<int?> TakenIds = new List<int?>();
public CategoryMapViewModel(List<PostCategoryModels> categoriesModels)
{
string map = "";
map = BuildCategoriesMap(categoriesModels, map);
this.Map = new HtmlString(map);
}
private string BuildCategoriesMap(List<PostCategoryModels> categories, string map)
{
if (categories != null && categories.Count > 0)
{
map += "<ul>";
foreach (PostCategoryModels cat in categories)
{
if ((!cat.CategoryId.HasValue) || (cat.CategoryId.HasValue && (!TakenIds.Contains(cat.CategoryId))))
{
map += "<li>" + cat.Name;
List<PostCategoryModels> subCats = categories.Where(c => c.IdPostCategoryParent == cat.CategoryId).ToList();
if (subCats.Count() > 0)
{
//map += BuildCategoriesMap(subCats, map);
//BuildCategoriesMap(subCats, map);
map += BuildCategoriesMap(subCats, "");
}
map += "</li>";
}
TakenIds.Add(cat.CategoryId);
}
map += "</ul>";
}
return map;
}
}
am I wrong ? can someone give me the best and easiest way to do it ? if yes, please do it!
Kind Regards!
The problem is that you are searching in categories for the children, but when processing the direct children, you only pass the direct children through, so when it searches for sub categories, there are none that match.
One solution is to keep a reference to categories in your class and use that when searching for sub categories.
ie:
public class CategoryMapViewModel
{
public HtmlString Map { get; private set; }
private List<int?> TakenIds = new List<int?>();
private List<PostCategoryModels> _categories;
public CategoryMapViewModel(List<PostCategoryModels> categoriesModels)
{
_categories = categoriesModels ?? new List<PostCategoryModels>();
string map = BuildCategoriesMap(_categories);
this.Map = new HtmlString(map);
}
private string BuildCategoriesMap(List<PostCategoryModels> categories)
{
var map = "";
if (categories.Count > 0)
{
map += "<ul>";
foreach (PostCategoryModels cat in categories)
{
if ((!cat.CategoryId.HasValue) || (cat.CategoryId.HasValue && (!TakenIds.Contains(cat.CategoryId))))
{
map += "<li>" + cat.Name;
List<PostCategoryModels> subCats = _categories.Where(c => c.IdPostCategoryParent == cat.CategoryId).ToList();
map += BuildCategoriesMap(subCats);
map += "</li>";
}
TakenIds.Add(cat.CategoryId);
}
map += "</ul>";
}
return map;
}
}
I've taken out a few redundant lines also
I am working in Slider Concept in ASP.NET MVC 2.
slider code snippet
<script type="text/javascript">
$(function () {
var abc = $('select#speed').selectToUISlider().next();
fixToolTipColor();
});
function fixToolTipColor() {
$('.ui-tooltip-pointer-down-inner').each(function () {
var bWidth = $('.ui-tooltip-pointer-down-inner').css('borderTopWidth');
var bColor = $(this).parents('.ui-slider-tooltip').css('backgroundColor')
$(this).css('border-top', bWidth + ' solid ' + bColor);
});
}
</script>
<form action="#">
<fieldset>
<select name="speed" id="speed">
<option value="Poor">Poor</option>
<option value="Good">Good</option>
<option value="Med">Med</option>
<option value="VeryGood">VeryGood</option>
<option value="Excellent">Excellent</option>
</select>
</fieldset>
</form>
I don't understand how to load the slider with dynamic values (based on calculations or numbers from the database)
How do I do this?
Right now I populate a dropdownlist using the following SQL. How can this be used to populate the slider?
private void PopulateGradeScale(string tenantID)
{
List<scale> AttributesList = new List<scale>();
if (!string.IsNullOrEmpty(tenantID))
{
Context.SetPrivilegeContext(PrivilegeConstant.ViewEmployee);
Dictionary<string, scale> Attributes = Proxy.GetGrade(UserIdentity.TenantID);
if (Attributes != null && Attributes.Count > 0)
{
AttributesList = Attributes.Values.ToList();
}
}
if (!string.IsNullOrEmpty(tenantID))
ViewData["Grade"] = new SelectList((IEnumerable)AttributesList, "Identifier", "Name");
else
ViewData["Grade"] = new SelectList((IEnumerable)AttributesList, "Identifier", "Name");
}
As always you start with defining a view model which will represent your data for this given view:
public class SliderViewModel
{
public string SelectedSpeed { get; set; }
public IEnumerable<Item> Items { get; set; }
}
public class Item
{
public string Value { get; set; }
public string Text { get; set; }
}
Next you have a controller action which will use a repository to query the database and fill the view model which will be passed to a strongly typed view:
public ActionResult Index()
{
var model = new SliderViewModel
{
Items = new[]
{
new Item { Value = "Poor", Text = "Poor" },
new Item { Value = "Good", Text = "Good" },
new Item { Value = "Med", Text = "Med" },
new Item { Value = "VeryGood", Text = "VeryGood" },
new Item { Value = "Excellent", Text = "Excellent" }
}
};
return View(model);
}
and finally you use an HTML helper in the view to generate the dropdown":
<%= Html.DropDownListFor(
x => x.SelectedSpeed,
new SelectList(Model.Items, "Value", "Text")
) %>