Bootstrap Selectpicker multiselect doesn't keep selection after submit - c#

I am using the bootstrap selectpicker for a multiselect dropdown menu to filter items of a table in a mvc5 web app. Everything works fine so far, but i am having trouble to keep the selected filters selected after submitting. So i can read the selected filters in the controller, but after that, there is only the first previously selected filter still shown as selected after the submit. I want all chosen filters to be still selected. How can I reach this?
Here ist my Code, the ViewModel contains:
public MultiSelectList AvailableUser_ID { get; set; }
private List<string> _selectedUserId = new List<string>();
public List<string> SelectedUserId
{
get { return _selectedUserId; }
set { _selectedUserId = value; }
}
The Controller (Post):
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Index([Bind(Include = "SelectedUserId,SelectedUserInteractionTypesId")] IndexUserInteractionViewModel indexUserInteractionViewModel)
{
indexUserInteractionViewModel.UserInteractionViewModels = new List<UserInteractionViewModels>();
indexUserInteractionViewModel.AvailableUser_ID = new MultiSelectList(db.AspNetUsers.ToList(), "Id", "Email", indexUserInteractionViewModel.SelectedUserId);
// Filter Function: selectedUserId contains all the Ids of the previously selected filters
foreach (string selectedUserId in indexUserInteractionViewModel.SelectedUserId)
{
if (userInteraction.AspNetUsers_Id.Equals(selectedUserId))
// ...
}
}
And the View:
<script type="text/javascript">
$(document).ready(function () {
$('.selectpicker').selectpicker();
});
</script>
<th>#Html.DropDownListFor(Model => Model.SelectedUserId, Model.AvailableUser_ID as MultiSelectList, new { #id = "userFilter", #class = "selectpicker", #multiple = "mulitple", data_live_search = "true" })</th>
So how can I keep the Selection selected?
Unfortunately I have little js-knowledge and i am assuming that i could solve it in the js-script. I am hoping for some experts here. Thank you!

A colleague of mine found a solution, this is what works:
var selectedList = #Html.Raw(Json.Encode(Model.SelectedUserId));
if(selectedList.length > 0){
var result = '[';
for (i = 0; i < selectedList.length; i++) {
result += '"' + selectedList[i] + '",';
}
result = result.slice(0, -1); //remove last comma
result += ']';
$('.selectpicker').selectpicker('val', JSON.parse(result1));
}else{
$('.selectpicker').selectpicker();
}

Related

ASP.NET Model Binding for Multiple Dropdownlist

i want to set multiple dropdownlist with value from db.
Here the code:
VIEW
#Html.DropDownListFor(model => model.rcf_data.lnkt_PIC, Model.Emp_list.EmployeList, new { #class = "show-tick form-control", id = "EmployeeList9", multiple = "multiple" })
CONTROLLER
In the controller, i use MergeModel
public ActionResult Edit(String rcf_id)
{
//List<RCFHistory> list_history_status =
MergeModel model = new MergeModel();
model.rcf_history = new List<RCFHistory>();
model.rcf_history = GetRCFHistory(rcf_id);
model.rcf_data = list_rcf.Where(r => r.lnkt_name == rcf_id).FirstOrDefault();
model.Emp_list = new ListEmployeeMaster();
model.Emp_list.EmployeList = new SelectList(GetAllEmployee(), "emp_id", "emp_name");
return View(model);
}
private IEnumerable<EmployeeNameModel> GetAllEmployee()
{
list_emp = new List<EmployeeNameModel>();
string apiUrl = "http://localhost:6161/Service1.svc";
HttpClient client = new HttpClient();
HttpResponseMessage response = client.GetAsync(apiUrl + string.Format("/GetAllEmployee")).Result;
if (response.IsSuccessStatusCode)
{
list_emp = (new JavaScriptSerializer()).Deserialize<List<EmployeeNameModel>>(response.Content.ReadAsStringAsync().Result);
}
return list_emp;
}
I want to set value from model.rcf_data.lnkt_PIC which is List<String> into DropDownListFor in the view. But it keep showing empty field.
For single DropDownListFor, this line work for me, and it's showing value that i get from DB:
#Html.DropDownListFor(model => model.rcf_data.lnkt_2ndapprovalid, Model.Emp_list.EmployeList, Model.rcf_data.lnkt_2ndapprovalid, new { id = "EmployeeList2", #class = "show-tick form-control" })
Just changing from DropDownListFor to ListBoxFor solved my problem. No other changes happen within my code

How do I find the value of a ViewBag variable list item in C#

I have a case where I am loading a combobox based on a viewbag where it is populated by a select list
So the selectlist is populated via this code
private SelectList GetBranches(int? selected = null)
{
IPracticeRepository rep = db.GetPracticeRepository();
var curPracticeId = GetUser()?.PracticeId ?? 0;
var branches = rep.GetById(curPracticeId).Branches;
var selectList = new List<SelectListItem>();
if (selected == null) selectList.Add(new SelectListItem() { Selected = true, Text = "", Value = "" });
foreach (var item in branches)
{
if (item.CanCollectReceipts)
selectList.Add(new SelectListItem() { Value = item.Id.ToString(), Text = item.Name, Selected = selected == item.Id });
}
if (selectList.Count == 0) selectList.Add(new SelectListItem() { Selected = true, Text = "", Value = "" });
return new SelectList(selectList, "Value", "Text");
}
...
ViewBag.Branches = GetBranches(invoice.Visit.Branch.Id)
I then want to set a variable which will hide or show the combo box based on whether the first value is "" as set when the count is 0.
if (ViewBag.Branches == "")
{
setSite = false;
}
else
{
setSite = true;
}
ViewBag.Setsite = setSite;
So obviously the above code is not working but I am trying to figure out how do I find the value of that first value in the viewbag so I can set my variable.
if (((SelectList)ViewBag.Branches).First().Value == "")
Although, if you are still on the controller side, then it's probably cleaner to
var the_list = GetBranches(invoice.Visit.Branch.Id); // Guarantees at least 1 element in the list
ViewBag.Branches = the_list;
if (the_list.First().Value == "")
{
...
}
Although still, if you are still on the controller side, you probably don't want to save setSite in the bag in the first place, given that it's strictly linked to the contents of the list. So you probably should move that part to the view:
#{
bool setSite = (((SelectList)ViewBag.Branches).First().Value != "";
}
// using setSite in the markup

C#: How to using global variable with Javascript

everyone!
I'm learning ASP.NET MVC and have some question.
My problem is Passing Data from View to Controller.
This my Code:
#{
string listID = "";
}
and I try to use this variable:
function SubmitDelete() {
var listId = "";
var x = document.getElementsByName("IsCheck");
for (var i = 0; i < x.length; i++) {
if (x[i].checked == true) {
listId += x[i].value + ", ";
};
}
#listID = listId;
return listId;
}
Finalize, I want to pass #listID to Controller:
#using (Html.BeginForm("DeleteChecked", "Category", new { listID }, FormMethod.Post)){ }
It is simple problem about multi delete with checkbox.
Help me, please.
You cannot pass a javascript variable to your controller.
But you can post it as part form data with the help of hidden field.
Better add a hidden field and set it in a Javascript and post
#using (Html.BeginForm("DeleteChecked", "Category", FormMethod.Post)){
Html.HiddenFieldFor(m=>m.MyList, new {#id="my-list-data"})
..other controls and your submit button
}
In a Javascript
function SubmitDelete() {
var listId = "";
var x = document.getElementsByName("IsCheck");
for (var i = 0; i < x.length; i++) {
if (x[i].checked == true) {
listId += x[i].value + ", ";
};
}
$('#my-list-data').val(listId);
}
You cannot do that.
The aspx\ascx\cshtml etc. page is built in the server side while the js is computed on the client's side.
You can add C# string to js functions but they will be hard coded when they get to the client.
All the C# expression are evaluated before they get to the client and before the js is computed.
Here's an example:
This is what you see on the aspx\ascx\cshtml file.
<%
string str = 'test';
%>
function jsFunc(){
var myVar = '<%=str%>';
}
This is what the client gets:
function jsFunc(){
var myVar = 'test';
}

How to set the display value and the value of autocompleted textbox?

I've made an auto-completion in a textbox using Jquery as follows:
$(document).ready(function () {
$('#searchCollabo').autocomplete({
source: '#Url.Action("AutocompleteCollabo")'
});
});
So the data come from the method AutocompleteCollabo which looks like that:
public ActionResult AutocompleteCollabo(string term)
{
int NumDossier = StructureData.DonneNumDossier((string)Session["NumCRPCEN"], (string)Session["MotDePasse"]);
List<Contact> ListeContacts = StructureData.DonneListeElementDossier(NumDossier);
Contact[] tabContacts = new Contact[ListeContacts.Count()];
int count = 0;
foreach (Contact contact in ListeContacts)
{
tabContacts[count] = contact;
count++;
}
var collaborateurs = tabContacts;
var collaborateurFiltres = collaborateurs.Where(
item => item.Nom.Contains(term) || item.Fonction.Contains(term)
);
return Json(collaborateurFiltres, JsonRequestBehavior.AllowGet);
}
The returned json contains a list of object as below:
[{"ListeFonctions":[],"IdContact":91264,"Nom":"solecki","Prenom":"hubert","Email":"hsolecki#mail.c"}]
Now I would like to set the display name (Name + function) and the value which I want to get when I select a row of the auto-completion. Do you have an Idea ?
I found out how to do it, it may help.
The function that I'm calling throught an Ajax call:
public ActionResult AutocompleteCollabo(string term)
{
int NumDossier = StructureData.DonneNumDossier((string)Session["NumCRPCEN"], (string)Session["MotDePasse"]);
List<Contact> ListeContacts = StructureData.DonneListeElementDossier(NumDossier);
var tabContactFull = ListeContacts.Where(contact => contact.Nom.Contains(term) || contact.Prenom.Contains(term) || contact.Fonction.Contains(term));
var tabInfosUtiles = tabContactFull.Select(contact => new { label = contact.Nom + " " + contact.Prenom + " ("+contact.Fonction+") ", value = contact.Nom + " " + contact.Prenom + " ("+contact.Fonction+") ", id = contact.IdContact }).ToArray();
// We set our needed informations with a title like "Label", "Value"
// So the auto-complete can find by itself which data to display and which are for the value
return Json(tabInfosUtiles, JsonRequestBehavior.AllowGet);
}
My Ajax call and the success event:
$(document).ready(function () {
$('#searchCollabo').autocomplete({
source: '#Url.Action("AutocompleteCollabo")',
select: function (event, ui) {
$("#idElement").val(ui.item.id);
// If you want to get the value : ui.item.Value
// If you want to get the label : ui.item.Label
}
});
});
Hope it helps some of you !

Having a certain ID in the drop down list always at the bottom

I have a subject dropdownlist for a contact form. I always want the Other to be at the bottom of the list. The reason I ask this is because I created a controller so if I wanted to add more subjects I could do so. Anyways suggestions or ways I could go about making sure that the position of the Other subject is always on the bottom of the list?
public void PrepareSubjectCombo()
{
// Grab a list of subjects for the dialog box
IRepository<Subject> subjectRepository = new Repository<Subject>();
List<Subject> subjects = subjectRepository.GetAll().OrderBy(t => t.Position).ToList();
subjects.Insert(0, new Subject() { ID = 0, Name = "- Please Select -" });
ViewData["Subjects"] = subjects;
}
I have posted my combo box if this is of any help
You should simply use the proper overload of the DropDownList helper when rendering your dropdown in the view instead of trying to insert some dummy items into the collection:
public void PrepareSubjectCombo()
{
// Grab a list of subjects for the dialog box
IRepository<Subject> subjectRepository = new Repository<Subject>();
List<Subject> subjects = subjectRepository.GetAll().OrderBy(t => t.Position).ToList();
ViewData["Subjects"] = subjects;
}
and then in the view:
#Html.DropDownList(
"selectedSubject",
new SelectList(ViewData["Subjects"] as List<Subject>, "ID", "Name"),
"- Please Select -"
)
Now this being said, everytime I see someone using ViewData/ViewBag/ViewCrap instead of strongly typed views and view models I get sick and I feel myself into the obligation to show the correct way of doing this.
As always you start with a view model:
public class MyViewModel
{
public string SelectedSubject { get; set; }
public IEnumerable<SelectListItem> Subjects { get; set; }
}
then you have a controller action which will take care of populating this view model:
public ActionResult Index()
{
// TODO: You definitively don't want to hardcode your repository like this
// but use a constructor injection or this action will be impossible to unit test
IRepository<Subject> subjectRepository = new Repository<Subject>();
var subjects = subjectRepository.GetAll().OrderBy(t => t.Position).ToList();
var model = new MyViewModel
{
Subjects = subjects.Select(x => new SelectListItem
{
Value = x.ID.ToString(),
Text = x.Name
})
};
return View(model);
}
and finally in your strongly typed view:
#model MyViewModel
#Html.DropDownListFor(
x => x.SelectedSubject,
new SelectList(Model.Subjects, "Value", "Text"),
"- Please Select -"
)
DropDownList1.DataSource = YourDataSource;
DropDownList1.DataBind();
//Insert Other subject to the end
ListItem litem = new ListItem(" Other subject ", "value");
DropDownList1.Items.Insert(DropDownList1.Items.Count, litem);
Modify your code as shown below:
public void PrepareSubjectCombo()
{
// Grab a list of subjects for the dialog box
IRepository<Subject> subjectRepository = new Repository<Subject>();
List<Subject> subjects = subjectRepository.GetAll().OrderBy(t => t.Position).ToList();
subjects.Insert(0, new Subject() { ID = 0, Name = "- Please Select -" });
// Add this line
// Make sure you use the correct ID for the "Other" subject
subjects.Add(new Subject() { ID = 100, Name = "Other" });
// If you determine the ID based on the list, simply set the ID = subjects.Count + 1
int otherID = subjects.Count + 1;
subjects.Add(new Subject() { ID = otherID, Name = "Other" });
ViewData["Subjects"] = subjects;
}

Categories

Resources