I have created a process for creating a dynamic dropdown list group on button click with the given number of the dropdown lists in an input field. Then i collect a user list from the database and showing all in these doropdown lists. Now my job is that if one user is selected by any dropdown then that option must be disabled for the others. How can i do that?
I tried that by disabling the selected option from the list, But when i am disabling the selected option, the dropdown ng-model that selected that option is becoming null.
For creating a dynamic Dropdown list:
<div class="col-md-3">
<div class="form-group-sm">
<input class="form-control" ng-model="numberOfLevels"
type="text" name="numberOfLevels" id="numberOfLevels">
</div>
</div>
<div class="col-md-7" >
<div class="form-group-sm">
<a href="#" type="button" class="btn btn-box-tool btn-primary"
style="color:white;"
ng-click="addLevels(numberOfLevels)" >Manage</a>
</div>
</div>
$scope.addLevels = function (num) {
getAllUsers();
$scope.showLevels = true;
$scope.levels = [];
var count = 0;
if (num > 0) {
while (count < num) {
count++;
//console.log(count);
$scope.levels.push({ 'key': count, 'value': count });
//console.log(count);
}
}
//console.log($scope.levels);
//getAllUsers();
$scope.approversInputList = [];
}
<div class="col-md-12" ng-show="showLevels" ng-repeat="a in levels">
<div class="form-group">
<div class="col-md-4">
<label for=" username">
Approver {{a.value}} :
</label>
<select class="browser-default custom-select form-control has-error"
ng-model="abc[a.value]"
ng-change="setApprovers(selectedFileId, selectedNoteSheetId,a.value, abc[a.value])">
<option></option>
<option id="select" ng-repeat="user in userList"
value="{{user.Id}}" ng-disabled="user.Disabled">
{{user.UserName}}
</option>
#*<option id="select" ng-repeat="user in userList"
value="{{user.Id}}"
ng-disabled="disabledList[user.Id]">
{{user.UserName}}
</option>*#
</select>
</div>
<div class="col-md-7">
</div>
</div>
</div>
User List View Model:
public int Id { get; set; }
public string UserName { get; set; }
public bool Disabled { get; set; }
AngularJs Code for Disabling Selected Option:
$scope.abc = {};
$scope.$watch('abc', function (newVal, oldVal) {
//console.log($scope.userList);
var aaa = $scope.approversInputList;
for (var i = 0; i < $scope.userList.length; i++) {
$scope.userList[i].Disabled = false;
//console.log($scope.abc);
angular.forEach($scope.abc, function (value) {
if ($scope.userList[i].Id == value) {
$scope.userList[i].Disabled = true;
//$scope.disabledList[value] = true;
}
});
}
//console.log($scope.disabledList);
}, true);
When the selected option is disabled the dropdown should show the selected username.
This is happening because your userList is only one instance for all select. So you set disabled in userList and it propagates to all the levels.
u can try this, it will be difficult to solve it exactly until u give a minimal reproducible example:
<select class="browser-default custom-select form-control has-error"
ng-model="abc[a.value]"
ng-change="setApprovers(selectedFileId, selectedNoteSheetId,a.value, abc[a.value])">
<option></option>
<option id="select{{$index}}" ng-repeat="user in userList"
value="{{user.Id}}" ng-disabled="abc[a.value] == user.Id">
{{user.UserName}}
</option>
</select>
And remove your for loop altogether. if ng-disabled="abc[a.value] == user.Id" does not work then instead of using ng-diabled use some class if the condition is met and do some css on that class to make it disabled urself.
I am trying to update a drop down based on the users selection in the first drop down. I found this SO post on the topic, but Im not quite sure how to add the jquery to filter values to my Razor view. Can someone point me in the right direction?
My view so far:
#using System.Security.Claims;
#model UpdateClaimFormModel;
<h2>UpdateClaimView</h2>
#using (#Html.BeginForm())
{
<select name="emailcheese">
<option selected disabled>Select User</option>
#foreach (var i in Model.UserNames)
{
<option>#i.ToString()</option>
}
</select>
<select name="authpolicy">
<option selected disabled>Select Claim:</option>
#foreach (var i in Model.UserClaims)
{
<option>#i.Type.ToString()</option>
}
</select>
<div class="form-group">
<button type="submit" class="btn btn-default">Whoo</button>
</div>
}
My Goal:
Select User [bob, bill, jim]
Select Claim: If user bob:[1,2,3], If user bill:[1,4,8], If user him:[4,5,6]
so simpley you can do something like this
#using (#Html.BeginForm())
{
<select name="emailcheese" id="selectUserNames">
<option selected disabled>Select User</option>
#foreach (var i in Model.UserNames)
{
<option>#i.ToString()</option>
}
</select>
<select name="authpolicy" id="selectAuthPolicy">
</select>
<div class="form-group">
<button type="submit" class="btn btn-default">Whoo</button>
</div>
}
now in the script part
$(function(){
var userClaims = #Html.Raw(Json.Encode(Model.UserClaims));
$(document).on('change','#selectUserNames'function(){
var selectedVal = $(this).val();
if(selectedVal == 'bob')
{
var html ='<option selected disabled>Select Claim:</option>';
for(var i=1;i<userClaims.length;++i)
{
if(i==1||i==2||i==3)
{
html=html+'<option>'+userClaims[i].Type+'</option>';
}
}
$('#selectAuthPolicy').html(html);
}
})
})
this is just a basic dea of how you can achieve this i just tried for bob there are many other ways to immplement ths
I'm not getting the behavior I'm looking for. Say I've got a html template in Meteor called Teacher. It has two selectors, a 'week' selector and a 'sunday-lessons' selector (I've simplified the template somewhat here):
<template name="Teacher">
{{#each TeacherName}}
<div class="row">
<div class="input-field col s2 fullModal">
<select class="teacher-week-selector" id="week-selector">
<option value="Off" disabled selected>Week</option>
<option value="Week1">Week 1</option>
<option value="Week2">Week 2</option>
<option value="Week3">Week 3</option>
<option value="Week4">Week 4</option>
<option value="Week5">Week 5</option>
</select>
</div>
</div>
<div class="row">
<div class="input-field col s1 fullModal">
<select id="sunday-lessons">
<option value="Off" disabled selected>{{sundayLesson}}</option>
<option value=1>1</option>
<option value=2>2</option>
<option value=3>3</option>
<option value=4>4</option>
<option value=5>5</option>
<option value=6>6</option>
</select><label>SUN</label>
</div>
</div>
{{/each}}
</template>
In this case, {{#each TeacherName}} is returning ONE document since it returns an array with the document of interest in it.
I'm trying to get the behavior such that when the week selector is changed, it grabs the state of certain document properties in the database and inserts them into the sunday selector.
So I set a Session value first when the template renders:
Template.Teacher.onRendered(function () {
Session.set('WeekNumber', undefined);
});
Then in the events template I listen for the selector to change:
Template.Teacher.events({
'change #week-selector': function(){
var sselect = document.getElementById('week-selector').value;
Session.set('WeekNumber', sselect);
}
});
Then in the template helper I create a function that grabs the Session value and returns the value I want:
Template.Teacher.helpers({
sundayLesson: function () {
var lessonNum = Session.get('WeekNumber');
if (lessonNum === "Week1")
return Lessons.Week1.Sunday;
else if (lessonNum === "Week2")
return Lessons.Week2.Sunday;
else if (lessonNum === "Week3")
return Lessons.Week3.Sunday;
else if (lessonNum === "Week4")
return Lessons.Week4.Sunday;
else if (lessonNum === "Week5")
return Lessons.Week5.Sunday;
}
});
Even if I try to have the function return a primitive:
if (lessonNum === "Week1")
return 3;
Nothing happens. I'm expecting the 3 to be placed in the sunday-lesson selector at the moment the week selector is changed. I can see the value of the Session change if I put in alert(lessonNum), but the condition statements don't appear to be re-evaluating to return the different value. Not sure where I'm going wrong.
EDIT:
Interesting find. If I place the {{sundayLesson}} OUTSIDE the selector, I can get the reactive 3 value when the Session changes.
<p>{{sundayLesson}}</p> <!-- this works -->
<select id="sunday-lessons">
<option value="Off" disabled selected>{{sundayLesson}}</option> <!-- Doesn't work -->
<option value=1>1</option>
<option value=2>2</option>
<option value=3>3</option>
<option value=4>4</option>
<option value=5>5</option>
<option value=6>6</option>
</select><label>SUN</label>
The answer was found in the Materialize documentation. In order to update the selector dynamically, I needed to re-initialize the selector like this:
Template.Teacher.helpers({
sundayLesson: function () {
var lessonNum = Session.get('WeekNumber');
if (lessonNum === "Week1") {
$('select').material_select();
return Lessons.Week1.Sunday;
}
else if (lessonNum === "Week2") {
$('select').material_select();
return Lessons.Week2.Sunday;
}
else if (lessonNum === "Week3") {
$('select').material_select();
return Lessons.Week3.Sunday;
}
else if (lessonNum === "Week4") {
$('select').material_select();
return Lessons.Week4.Sunday;
}
else if (lessonNum === "Week5") {
$('select').material_select();
return Lessons.Week5.Sunday;
}
}
});
Sort of clumsy, but that's the solution.
What option do I need to set to make a drop down box readonly when using MVCs Html.DropDownList?
I've tried things like....
Html.DropDownList("Types", Model.Types, new { _Enabled = "false" })
...and many different things along this line; alas no joy!
I thought this would be an easy.....and it probably is!
Try this
Html.DropDownList("Types", Model.Types, new { #disabled = "disabled" })
Regarding the catch 22:
If we use #disabled, the field is not sent to the action (Mamoud)
And if we use #readonly, the drop down bug still lets you change the value
Workaround: use #disabled, and add the field hidden after the drop down:
#Html.HiddenFor(model => model.xxxxxxxx)
Then it is truly disabled, and sent to the to the action too.
<script type="text/javascript">
$(function () {
$(document) .ajaxStart(function () {
$("#dropdownID").attr("disabled", "disabled");
})
.ajaxStop(function () {
$("#dropdownID").removeAttr("disabled");
});
});
</script>
I had to disable the dropdownlist and hide the primary ID
<div class="form-group">
#Html.LabelFor(model => model.OBJ_ID, "Objs", htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.DropDownList("OBJ_ID", null, htmlAttributes: new { #class = "form-control", #disabled = "disabled"})
#Html.HiddenFor(m => m.OBJ_ID)
#Html.ValidationMessageFor(model => model.OBJ_ID, "", new { #class = "text-danger" })
</div>
</div>
A tip that may be obvious to some but not others..
If you're using the HTML Helper based on DropDownListFor then your ID will be duplicated in the HiddenFor input. Therefore, you'll have duplicate IDs which is invalid in HTML and if you're using javascript to populate the HiddenFor and DropDownList then you'll have a problem.
The solution is to manually set the ID property in the htmlattributes array...
#Html.HiddenFor(model => model.Entity)
#Html.EnumDropDownListFor(
model => model.Entity,
new {
#class = "form-control sharp",
onchange = "",
id =` "EntityDD",
disabled = "disabled"
}
)
Or you can try something like this:
Html.DropDownList("Types", Model.Types, new { #readonly = "true" })
Put this in style
select[readonly] option, select[readonly] optgroup {
display: none;
}
I just do this and call it a day
Model.Id > -1 ? Html.EnumDropDownListFor(m => m.Property, new { disabled = "disabled" }) : Html.EnumDropDownListFor(m => m.Property)
#Html.DropDownList("Types", Model.Types, new { #disabled = "" })
Works
Html.DropDownList("Types", Model.Types, new { #disabled = "disabled" })
#Html.Hidden(Model.Types)
and for save and recover the data, use a hidden control
For completeness here is the HTML Helper for DropDownListFor that adds enabled parameter, when false select is disabled. It keeps html attributes defined in markup, or it enables usage of html attributes in markup, it posts select value to server and usage is very clean and simple.
Here is the code for helper:
public static MvcHtmlString DropDownListFor<TModel, TProperty>(this HtmlHelper<TModel> html, Expression<Func<TModel, TProperty>> expression, IEnumerable<SelectListItem> selectList, object htmlAttributes, bool enabled)
{
if (enabled)
{
return SelectExtensions.DropDownListFor<TModel, TProperty>(html, expression, selectList, htmlAttributes);
}
var htmlAttributesAsDict = HtmlHelper.AnonymousObjectToHtmlAttributes(htmlAttributes);
htmlAttributesAsDict.Add("disabled", "disabled");
string selectClientId = html.ViewContext.ViewData.TemplateInfo.GetFullHtmlFieldId(ExpressionHelper.GetExpressionText(expression));
htmlAttributesAsDict.Add("id", selectClientId + "_disabled");
var hiddenFieldMarkup = html.HiddenFor<TModel, TProperty>(expression);
var selectMarkup = SelectExtensions.DropDownListFor<TModel, TProperty>(html, expression, selectList, htmlAttributesAsDict);
return MvcHtmlString.Create(selectMarkup.ToString() + Environment.NewLine + hiddenFieldMarkup.ToString());
}
and usage, goal is to disable select if there is just one item in options, markup:
#Html.DropDownListFor(m => m.SomeValue, Model.SomeList, new { #class = "some-class" }, Model.SomeList > 1)
And there is one even more elegant HTML Helper example, no post support for now (pretty straight forward job, just use HAP and add hidden input as root element sibling and swap id's):
public static MvcHtmlString Disable(this MvcHtmlString previous, bool disabled, bool disableChildren = false)
{
if (disabled)
{
var canBeDisabled = new HashSet<string> { "button", "command", "fieldset", "input", "keygen", "optgroup", "option", "select", "textarea" };
var doc = new HtmlDocument();
doc.LoadHtml(previous.ToString());
var rootElements = doc.DocumentNode.Descendants().Where(
hn => hn.NodeType == HtmlNodeType.Element &&
canBeDisabled.Contains(hn.Name.ToLower()) &&
(disableChildren || hn.ParentNode.NodeType == HtmlNodeType.Document));
foreach (var element in rootElements)
{
element.SetAttributeValue("disabled", "");
}
string html = doc.DocumentNode.OuterHtml;
return MvcHtmlString.Create(html);
}
return previous;
}
For example there is a model property bool AllInputsDisabled, when true all html inputs should be disabled:
#Html.TextBoxFor(m => m.Address, new { placeholder = "Enter address" }).Disable(Model.AllInputsDisabled)
#Html.DropDownListFor(m => m.DoYou, Model.YesNoList).Disable(Model.AllInputsDisabled)
You could use this approach
Disabling all the options except the selected one:
<select>
<option disabled>1</option>
<option disabled>2</option>
<option selected>3</option>
</select>
This way the dropdown still submits, but the user can not select another value.
With jQuery
<script>
$(document).ready(function () {
$('#yourSelectId option:not(:selected)').prop("disabled", true);
});
</script>
try with #disabled and jquery, in that way you can get the value on the Controller.
Html.DropDownList("Types", Model.Types, new {#class = "your_class disabled", #disabled= "disabled" })
Add a class called "disabled" so you can enabled by searching that class(in case of multiples disabled fields), then you can use a "setTimeout" in case of not entering controller by validation attributes
<script>
function clickSubmit() {
$("select.disabled").attr("disabled", false);
setTimeout(function () {
$("select.disabled").attr("disabled", true);
}, 500);
}
</script>
submit button like this.
<button type="submit" value="Submit" onclick="clickSubmit();">Save</button>
in case of inputs, just use #readonly="readonly"
#Html.TextBoxFor("Types",Model.Types, new { #class = "form-control", #readonly= "readonly" })
You can set the select as readonly and then run some jquery to disable the options except the selected value. You cant change the value and it's included when the form is submitted.
$(document).ready(function () {
$('select option').removeAttr('disabled');
$('#readonlyTest').find('select[readonly] option').not('select[readonly] option[selected]').attr('disabled', 'disabled');
});
$('#submitButton').click(function(e) {
var formData = $('form').serialize();
$('#formData').html(formData);
});
body {
margin: 50px;
}
<link href="https://cdn.jsdelivr.net/npm/bootstrap#4.6.1/dist/css/bootstrap.min.css" rel="stylesheet"/>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<form>
<div class="form-group">
<label for="scopeReadonlyNoJs">Scope Readonly No Js</label>
<select class="form-control" id="scopeReadonlyNoJs" name="scopeReadonlyNoJs" readonly="readonly">
<option value="">Select..</option>
<option selected="selected" value="readonlyNoJsScopeValue1">Scope Value 1</option>
<option value="readonlyNoJsScopeValue2">Scope Value 2</option>
</select>
<small id="scopeReadonlyNoJsHelp" class="form-text text-muted">This is read only and no js is applied. It looks disabled but you can change the values.</small>
</div>
<div id="readonlyTest" class="form-group">
<label for="scopeReadonly">Scope Readonly</label>
<select class="form-control" id="scopeReadonly" name="scopeReadonly" readonly="readonly">
<option value="">Select..</option>
<option selected="selected" value="readonlyScopeValue1">Scope Value 1</option>
<option value="readonlyScopeValue2">Scope Value 2</option>
</select>
<small id="scopeReadonlyHelp" class="form-text text-muted">This is read only and is disabled via js by disabling the options except the selected one.</small>
</div>
<div class="form-group">
<label for="scopeDisabled">Scope Disabled</label>
<select class="form-control" id="scopeDisabled" name="scopeDisabled" disabled="disabled">
<option value="">Select..</option>
<option selected="selected" value="disabledScopeValue1">Scope Value 1</option>
<option value="disabledScopeValue2">Scope Value 2</option>
</select>
<small id="scopeDisabledHelp" class="form-text text-muted">This is disabled and wont be posted.</small>
</div>
<button id="submitButton" type="button">
Submit
</button>
</form>
<p id="formData">
</p>
I've create this answer after referring above all comments & answers.
This will resolve the dropdown population error even it get disabled.
Step 01
Html.DropDownList("Types", Model.Types, new {#readonly="readonly"})
Step 02
This is css pointerevent remove code.
<style type="text/css">
#Types {
pointer-events:none;
}
</style>
Then you can have expected results
Tested & Proven
I have a handlebars template that I am embedding in my html page. There is a select element with all of the available options already rendered. How can I set the selected value of the select list when I render my template?
<script id="my-template" type="text/x-handlebars-template">
<div id="my-modal">
<form action="/TestAction" method="post">
<input id="MyId" name="MyId" type="hidden" value="{{MyId}}" />
<label for="Test">Test: (optional)</label>
<select id="Test" name="Test">
<option value="">-- Choose Test --</option>
<option value="1">1</option>
<option value="2">2</option>
<option value="3">3</option>
<option value="4">4</option>
</select>
</form>
</div>
</script>
If you don't want to build out the option as part of the helper, you can use a combination of a small custom handlebars helper and parent context, denoted using the ../ syntax:
First write the helper:
Handlebars.registerHelper('selected', function(option, value){
if (option === value) {
return ' selected';
} else {
return ''
}
});
And then in your template you call your helper and pass in the parent context inside the each loop to check for selectedState
{{#each states}}
<option value="{{this}}" {{selected this ../selectedState}}>{{this}}</option>
{{/each}}
I took the {{#each}} helper as inspiration, and wrote a custom helper that does the same thing: loops over a list, and continually appends the contents of the arguments to an output string. (From here: Handlebars block helpers)
In this case, I'm not passing in a chunk of template HTML to serve as the function's options parameter, like you would when using {{#each}}. Instead I am just building up the <option>
tags by brute force, and testing every iteration of the context list. Lastly, I return a big long string of <option></option> tags, and hopefully one of them has selected="selected".
The function:
Handlebars.registerHelper('options_selected', function(context, test) {
var ret = '';
for (var i = 0, len = context.length; i < len; i++) {
var option = '<option value="' + context[i]+'"';
if (test.toLowerCase() == context[i].toLowerCase()) {
option += ' selected="selected"';
}
option += '>'+ Handlebars.Utils.escapeExpression(context[i]) + '</option>';
ret += option;
}
return new Handlebars.SafeString(ret);
});
The tag in use:
<script id="form-state" type="text/x-handlebars-template">
<select name="state">
{{{options_selected states selectedState}}}
</select>
</script>
Please suggest any edits that would improve this, thanks!
You can use values straight in the Handlebars template like so.
Handlebars Template
<select id="distance">
<option value="15" {{#if (isEqual 15 distance)}} selected {{/if}}>15</option>
<option value="25" {{#if (isEqual 25 distance)}} selected {{/if}}>25</option>
<option value="50" {{#if (isEqual 50 distance)}} selected {{/if}}>50</option>
<option value="100" {{#if (isEqual 100 distance)}} selected {{/if}}>100</option>
<option value="300" {{#if (isEqual 300 distance)}} selected {{/if}}>300</option>
</select>
Handlebars Helper
define(['hbs/handlebars'], function (Handlebars) {
'use strict';
Handlebars.registerHelper('isEqual', function (expectedValue, value) {
return value === expectedValue;
});
});
Here is a solution (built over EmberJS to ease the JS part)
I refactored your sample a little, to have objects for proposed values, which can by the way carry the selected attribute...
The template part:
<script type="text/x-handlebars" data-template-name="my-template">
<div id="my-modal">
<form action="/TestAction" method="post">
<input id="MyId" name="MyId" type="hidden" value="{{MyId}}" />
<label for="Test">Test: (optional)</label>
<select id="Test" name="Test">
<option value="">-- Choose Test --</option>
{{#each values}}
<option {{bindAttr value="id" selected="selected"}}>{{label}}</option>
{{/each}}
</select>
</form>
</div>
</script>
The JS part:
App.MyView = Ember.View.extend
templateName: 'my-template'
MyId: 42
values: [{
id: 1,
label: '1'
}, {
id: 2,
label: '2'
}, {
id: 3,
label: '3',
selected: true
}, {
id: 4,
label: '4'
}]
You can try it # http://jsfiddle.net/MikeAski/uRUc3/
I had same problem.
$('select').val(value);
This is how I solved it, I set the desired value with jQuery after rendering the template. Was surprisingly easy. (Maybe its also a way to keep the templates logicless)