Dropdown menu with icon in Knockout - javascript

Is there any possible way to create a dropdown that has a diffrent icon from fontawesome for each individuel option value? Or can I change the brackground color of each value? I prefer the circle icon from fontawesome where I can change the color of every record in the list.
I tried to add the Fontawesomecode of an Icon in the html part
<select data-bind="options: someList, optionsText: 'dropdownItemName', optionsValue: 'dropdownItemId', value: selectedSomeList, optionsCaption: ''" style="font-family: FontAwesome"></select>
I also tried to add it into the a <i></i> tag but it does nothing.
Does someone have an idea? Thanks you for the help

You can add the Unicode for the icon in the optionText binding (Unicode values are specified for each icon on font-awesome's site):
var viewModel = function() {
this.values = ko.observableArray([{
text: 'address-book \uf2b9',
value: 1
}, {
text: 'bookmark \uf02e',
value: 2
}, {
text: 'location-arrow \uf124',
value: 3
}]);
this.selectedValue = ko.observable(2);
}
ko.applyBindings(new viewModel());
select {
font-family: 'FontAwesome', 'Second Font name'
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.1/knockout-min.js"></script>
<link href="https://maxcdn.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css" rel="stylesheet"/>
<select data-bind="options: values,
optionsText: 'text',
optionsValue: 'value',
value: selectedValue">
</select>
(I borrowed the idea from this answer. But, it was being displayed as  instead of the icon. It took a while to figure out)

I might be late. But try this one. jsfiddle
var viewModel = function() {
this.values = ko.observableArray([{
text: 'Visa',
value: 1,
icon:'fa-cc-visa'
}, {
text: 'Discover',
value: 2,
icon:'fa-cc-discover'
}, {
text: 'Amex',
value: 3,
icon:'fa-cc-amex'
}]);
OptionsAfterRender = (option, item) => {
ko.applyBindingsToNode(option, { css: item.icon }, item);
};
this.selectedValue = ko.observable(2);
}
ko.applyBindings(new viewModel());
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.1/knockout-min.js"></script>
<link href="https://maxcdn.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css" rel="stylesheet"/>
<select style="font-family:fontAwesome" multiple="multiple" size="3" data-bind="options: values,
optionsText: 'text',
optionsValue: 'value',
value: selectedValue,
optionsAfterRender:OptionsAfterRender">
</select>

Related

AngularJS - ng-select not working as expected

I have a filter drop down for some tabular data that reads data from a local storage item, the select tag is shown below, and below that is the code to add items to the select tag and the model for the filter.
The issue is that whilst the data filtered is correct when you refresh the page, the selected item only shows the correct value if the local storage value is true.
No matter what value the local storage item is selected="selected" is always added to the "Excluded from Search" option.
Can't for the life of me work out why, any help advice appreciated.
<select class="form-control form-control-sm" ng-model="filterSearch" ng-change="setFilterS()" id="theFilterS" >
<option ng-selected="{{option.value == filterSearch}}" ng-repeat="option in filterSearchOptions" value="{{option.value}}" >{{option.DisplayName}}</option>
</select>
$scope.filterSearch = localStorage.getItem("FilterSearch");
$scope.filterSearchOptions = [{
value: '',
DisplayName: 'All',
}, {
value: 'false',
DisplayName: 'Included in Search',
}, {
value: 'true',
DisplayName: 'Excluded from Search',
}];
You should try with the ng-options directive which IMO gives a simpler approach then ng-repeat
angular.module('app',[]).controller('testCtrl',function($scope){
$scope.filterSearch = 'true';
$scope.filterSearchOptions = [{
value: '',
DisplayName: 'All',
}, {
value: 'false',
DisplayName: 'Included in Search',
}, {
value: 'true',
DisplayName: 'Excluded from Search',
}];
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="app" ng-controller="testCtrl">
<select
class="form-control form-control-sm"
ng-model="filterSearch"
ng-change="setFilterS()"
id="theFilterS"
ng-options="option.value as option.DisplayName for option in filterSearchOptions">
</select>
{{filterSearch}}
</div>

Update the value of a selected object in Vue

I wand to select an option from a multiple select field and update the prozent value of the selected objects:
<div id="assistenzen">
<form>
<select v-model="assistenz" multiple>
<option v-for="option in options" v-bind:value="option">
{{ option.text }}
</option>
</select>
<ul>
<li v-for="(assi, prozent) in assistenz">{{assi.text}}
<input v-model="assistenz" v-bind:value="prozent">
{{assi.prozent}}
</li>
</ul>
</form>
</div>
<script>
var assistenz = new Vue({
el: '#assistenzen',
data: {
assistenz: 'keine Assistenz',
options: [
{ text: 'One', value: 'A', prozent: '0' },
{ text: 'Two', value: 'B', prozent: '0' },
{ text: 'Three', value: 'C', prozent: '0' }
]
},
});
assistenz.config.devtools = true
</script>
This code creates an input for each selected option but, the whole option text is stored in the input as value. Also it does not update the property of the object.
currently i prefer 'watch':
watch: {
multiselect: function(indexes) {
for(var i = 0; i < this.options.length; i++)
this.options[i].show = indexes.indexOf(i) > -1;
}
}
full example:
https://jsfiddle.net/4xq3mj9o/
To update the value of the choosen objects I had reverenze the Item iterated in the for loop and bind the input model to the items value:
<div id="assistenzen">
<form>
<select v-model="assistenz" multiple>
<option v-for="option in options" v-bind:value="option">
{{ option.text }}
</option>
</select>
<ul>
<li v-for="assi in assistenz">{{assi.text}}
<input v-model="assi.prozent">
{{assi.prozent}}
</li>
</ul>
</form>
</div>
<script>
var assistenz = new Vue({
el: '#assistenzen',
data: {
assistenz: 'keine Assistenz',
options: [
{ text: 'One', value: 'A', prozent: '0' },
{ text: 'Two', value: 'B', prozent: '0' },
{ text: 'Three', value: 'C', prozent: '0' }
]
},
});
assistenz.config.devtools = true
</script>
Use vue-multiselect
Just use something like this
<Multiselect :options="Options" :value="Values" :multiple="true" #update="updateMultiValue"> </Multiselect>

jQuery Select2 issue with shown selection

I am working on a select menu where I use Select-2 plugin to customize it as I would like to. Thereby I have an issue I try to recreate the selected items in the input field. So when you select an item it appear as small grey list item in the input field.
Here is a FIDDLE which shows the issue I have.
There by this is the javascript code how I render my input field:
var selectMenuItems = [
{id: 'restaurant', value: 'restaurant'},
{id: 'shopping', value: 'shopping'},
{id: 'toilet', value: 'toilet'}
]
function formatSelectItem (selectItem) {
if (!selectItem.id) { return selectItem.value; }
var $selectItem = $(
'<img src="img/markers/'+ selectItem.id.toLowerCase() +'.png"/>' +
'<span class="select-item-text">'+ selectItem.value+"</span>"
);
return $selectItem;
};
$("[name='select']").select2({
placeholder: "Selecteer een categorie",
templateResult: formatSelectItem,
data: selectMenuItems
}).on("change", function(e){
console.log(e);
$('.select-multiple :selected').each(function(i, selected) {
var selectedValue = $(selected).val();
$('.select2-selection__choice').text(selectedValue);
});
});
The problem is that when I select an item it appears with text inside the input field but if I select multiple all the items will change to that last selected item text. How can I only bind this .text() to that specific select item?
In the documentation of the plugin Select-2 plugin there is an example of called "Templating" where they don't have to appent the text or image to the selected item..
Working fiddle.
What you looking for is every time to loop through the selcted values provided by $(this).val() and append the value to the .select2-selection__choice by index using .eq() :
$("[name='select']").select2({
placeholder: "Selecteer een categorie",
templateResult: formatSelectItem,
data: selectMenuItems
}).on("change", function(e){
$.each($(this).val(), function(i, selected) {
$('.select2-selection__choice').eq(i).prepend(selected+' ');
});
});
NOTE : Use prepend() instead of tex() to preserve the 'X' in the tag.
Hope this helps.
(function($) {
$(function() {
var selectMenuItems = [
{id: 'restaurant', value: 'restaurant'},
{id: 'shopping', value: 'shopping'},
{id: 'toilet', value: 'toilet'}
]
function formatSelectItem (selectItem) {
if (!selectItem.id) { return selectItem.value; }
var $selectItem = $(
'<img src="img/markers/'+ selectItem.id.toLowerCase() +'.png"/>' +
'<span class="select-item-text">'+ selectItem.value+"</span>"
);
return $selectItem;
};
$("[name='select']").select2({
placeholder: "Selecteer een categorie",
templateResult: formatSelectItem,
data: selectMenuItems
}).on("change", function(e){
$.each($(this).val(), function(i, selected) {
$('.select2-selection__choice').eq(i).prepend(selected+' ');
});
});
});
})(jQuery);
.flag-text { margin-left: 10px; }
.select2 {
width: 100% !important;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<link href="https://cdnjs.cloudflare.com/ajax/libs/select2/4.0.0/css/select2.min.css" rel="stylesheet"/>
<script src="https://cdnjs.cloudflare.com/ajax/libs/select2/4.0.0/js/select2.min.js"></script>
<select id="type" name="select" class="select-multiple" multiple="multiple" data-role="none"></select>
Snippet using pictures :
(function($) {
$(function() {
var selectMenuItems = [
{id: 'restaurant', value: 'restaurant', img: 'https://www.hughesinsurance.co.uk/img/front/map-marker.png'},
{id: 'shopping', value: 'shopping', img: 'http://king-of-truck.byclickeat.fr/media/cache/square_40/front/bundle/clickeat/img/map-marker.png'},
{id: 'toilet', value: 'toilet', img: 'http://www.onebabyowner.co.uk/sites/all/themes/onebabyowner/img/icon/map-marker.png'}
]
function formatSelectItem (selectItem) {
if (!selectItem.id) { return selectItem.value; }
var $selectItem = $(
'<img src="'+ selectItem.img +'"/>' +
'<span class="select-item-text">'+ selectItem.value+"</span>"
);
return $selectItem;
};
$("[name='select']").select2({
placeholder: "Selecteer een categorie",
templateResult: formatSelectItem,
data: selectMenuItems
}).on("change", function(e){
$.each($(this).val(), function(i, selected) {
$('.select2-selection__choice').eq(i).prepend(selected+' ');
});
});
});
})(jQuery);
.flag-text { margin-left: 10px; }
.select2 {
width: 100% !important;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<link href="https://cdnjs.cloudflare.com/ajax/libs/select2/4.0.0/css/select2.min.css" rel="stylesheet"/>
<script src="https://cdnjs.cloudflare.com/ajax/libs/select2/4.0.0/js/select2.min.js"></script>
<select id="type" name="select" class="select-multiple" multiple="multiple" data-role="none"></select>
Here is the shortest method:
$('.select-multiple :selected').each(function(i, selected) {
$('.select2-selection__choice').eq(i).text($(this).val());
});
If you want to include images in options selected , use templateSelection function.You can override the display of the selection by setting the templateSelection option to a JavaScript function.
(function($) {
$(function() {
var selectMenuItems = [
{id: 'restaurant', text: 'restaurant', img: 'http://www.freeiconspng.com/uploads/restaurant-icon-png-7.png'},
{id: 'shopping', text: 'shopping', img: 'http://www.pngall.com/wp-content/uploads/2016/04/Shopping-Free-PNG-Image.png'},
{id: 'toilet', text: 'toilet', img: 'http://www.freeiconspng.com/uploads/toilet-icon-png-32.png'}
]
function formatSelectItem (selectItem) {
if (!selectItem.id) { return selectItem.text; }
var $selectItem = $(
'<img src="'+ selectItem.img +'" width="50px" height="50px"/>' +
'<span class="select-item-text">'+ selectItem.text+"</span>"
);
return $selectItem;
};
function formatState (opt) {
if (!opt.id) {
return opt.text;
}
var $opt = $(
'<span><img src="'+opt.img +'" width="50px" height="50px"/>' + opt.text + '</span>'
);
return $opt;
};
$("[name='select']").select2({
placeholder: "Selecteer een categorie",
templateResult: formatSelectItem,
templateSelection: formatState,
data: selectMenuItems
});
});
})(jQuery);
.flag-text { margin-left: 10px; }
.select2 {
width: 100% !important;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<link href="https://cdnjs.cloudflare.com/ajax/libs/select2/4.0.0/css/select2.min.css" rel="stylesheet"/>
<script src="https://cdnjs.cloudflare.com/ajax/libs/select2/4.0.0/js/select2.min.js"></script>
<select id="type" name="select" class="select-multiple" multiple="multiple" data-role="none"></select>
In your code
$('.select-multiple :selected').each(function(i, selected) {
var selectedValue = $(selected).val();
$('.select2-selection__choice').text(selectedValue);
});
You need to split the selectedValue into the values and search each of those to put in the text appropriate for that index of values.
In other words, replace that code as such:
$('.select-multiple :selected').each(function(i, selected) {
var selectedValue = $(this).val();
$('.select2-selection__choice').eq(i).text(selectedValue);
});
I thought I had to do this with jquery but when I changed the Array of selectMenuItems value to text the plugin does the work for me:
var selectMenuItems = [
{id: 'restaurant', text: 'restaurant'},
{id: 'shopping', text: 'shopping'},
{id: 'toilet', text: 'toilet'}
]
Just a simple fix where I thought I could set any property there

Knockout select binding cannot get selectedOptions to work

In my markup I have a simple <select> tag hat I've bound with Knockout JS, like so:
<select data-bind="options: CountriesOptions, optionsText: 'Text', optionsValue: 'Value', selectedOptions: SelectedCountries" multiple></select>
My view-model looks like this (simplified)
public class CountryViewModel
{
public List<SelectListItem> CountriesOptions { get; set; }
public int[] SelectedCountries { get; set; }
}
And in my controller I'm populating the model like so:
public ActionResult Edit()
{
using(var db = new DatabaseContext())
{
var model = new CountryViewModel();
model.CountriesOptions = db.Countries.Select(c => new SelectListItem
{
Value = "" + c.CountryId,
Text: c.Name
});
model.SelectedCountries = new int[]{1, 2, 3}
return View(model);
}
}
This example is very simplified but it does the job.
Problem
Whenever I load page and the binding is done, the <select> is filled with all the countries, which is the way I want it, but the selectedOptions is not working. Nothing is selected at all, thought my array looks exactly like int[]{1, 2, 3}. I'm not quite sure why this isn't working.
EDIT
JS scribbles
#using (Html.BeginScripts())
{
#Scripts.Render("~/bundles/knockout")
#Scripts.Render("~/bundles/jqueryval")
#Scripts.Render("~/bundles/jqueryui")
#Styles.Render("~/Content/themes/base/jqueryui-datepicker")
<script type="text/javascript">
// Create ViewModel
var vm = ko.mapping.fromJS(#Html.Raw(jsonData));
vm.loading = ko.observable(false);
// Init validation
ko.validation.init({ insertMessages: true, parseInputAttributes: true, messagesOnModified: true });
vm.errors = ko.validation.group(vm, { deep: true, observable: true, live: true });
ko.applyBindings(vm);
</script>
}
EDIT
I just found yet another issue with this binding. If I choose 2 countries from the select, they are NOT returned as selected. Bear in mind that this is SelectListItem's so they have a property called Selected
I'm trying to get all selected items when they return to the controller (when the user presses submit):
[HttpPost]
public ActionResult Edit()
{
var selectedCountries = model.Countriesoptions.Where(x => x.Selected).ToList();
}
But selectedCountries is an empty list.
The problem is probably that you miss the multiple attribute on your select. With it, things work as expected. Here's a demo with your code, with that attribute added and missing bits of code stubbed:
var data = {
CountriesOptions: [
{ Text: "USA", Value: 1 },
{ Text: "Greenland", Value: 4 },
{ Text: "Canada", Value: 3 },
{ Text: "Mexico", Value: 2 }
],
SelectedCountries: [ 1, 2, 3 ]
}
// Create ViewModel
var vm = ko.mapping.fromJS(data);
vm.loading = ko.observable(false);
// Init validation
ko.validation.init({ insertMessages: true, parseInputAttributes: true, messagesOnModified: true });
vm.errors = ko.validation.group(vm, { deep: true, observable: true, live: true });
ko.applyBindings(vm);
pre { background: white; padding: 10px; color: #333; font: 11px consolas; border: 1px solid #ddd; }
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.0/knockout-min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout.mapping/2.4.1/knockout.mapping.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout-validation/2.0.3/knockout.validation.min.js"></script>
<select data-bind="options: CountriesOptions,
optionsText: 'Text',
optionsValue: 'Value',
selectedOptions: SelectedCountries"
multiple>
</select>
<hr>Debug info: <pre data-bind="text: ko.toJSON($root, null, 2)"></pre>

data binding javascript knockout

This regards javascript knockouts
HTML
If run this row i get [Object, object]
<p><select data-bind="options: availableRole"></select></p>
If i run this row i get nothing
<p><select data-bind="options: availableRoles, value: availableRoles().title, optionText: 'availableRoles().title'"></select></p>
JAVASCRIPT
self.availableRoles = [
{ title: "Programmer" },
{ title: "Designer" }
];
How can i show the title programmer and designer?
You can use the optionsText binding to bind to a child value as described in the documentation:
<select data-bind="options: availableRoles, optionsText: 'title'"></select>
You can see a working example here.
You should provide property name in optionsText binding:
<select data-bind="options: availableRoles, optionText: 'title'"></select>
<select data-bind="options: availableRoles, optionsText: 'title', optionsCaption: 'Choose...'"></select>
For more on this, see: The "options" binding
One thing that all of these answers is missing is the ability to track what role you have selected in your view model. For this, you use the value binding in addition to the options binding.
Here's a working jsfiddle:
And here's the code pasted in for convenience:
var viewModel = {
availableRoles: [
{ title: "Programmer"},
{ title: "Designer" }
],
selectedRole: ko.observable()
};
ko.applyBindings(viewModel);​
<select data-bind="options: availableRoles, optionsText: 'title', optionsCaption: 'Select...', value: selectedRole"></select>
<pre data-bind="text: JSON.stringify(ko.toJS(selectedRole), null, 2)"></pre>
​
The solution is:
<select data-bind="options: availableRoles, optionsText: 'title'"></select>

Categories

Resources