I have created an application in AngularJS with a drop down with space in option using a filter. The application is working fine with the options in drop down with indentation space before the values but the problem is when a select an option which is having a space, the space is also shown in the view like as shown below
actually I want the indentation space within the drop-down options but only thing is that I don't want that space to be get displayed when selection shown above
can anyone please tell me some solution to prevent the space to display when selection
My code is as given below
JSFiddle
<select>
<option ng-repeat="(key, value) in headers">{{value | space}}
</option>
</select>
<select ng-model="selectedValue" ng-change="selVal = selectedValue.trim(); selectedValue=selVal">
<option ng-if="selVal">{{selVal}}</option>
<option ng-repeat="(key, value) in headers" ng-if="selVal != value.value">
{{value | space}}
</option>
</select>
This is as close as it gets without jquery, temporarily changing the view state of the option when it's chosen. If that doesn't satisfy you and you still want it to be shown indented when the dropdown menu is open, check out this question on how to detect the state of the select component and update the display function accordingly. Alternatively, you can create your own select directive and manage the details within that, but I doubt that's worth the trouble if you're not using it in many places.
var app = angular.module('myApp', []);
app.controller('ArrayController', function ($scope) {
$scope.headers = [{
value: 'value 1'
}, {
value: 'value 2',
mainId: 12
}, {
value: 'value 3'
}, {
value: 'value 4',
mainId: 14
}, {
value: 'value 5'
}, {
value: 'value 6',
mainId: 18
}];
$scope.chosen = $scope.headers[0].value;
$scope.display = function(header) {
var chosenObject = _.find($scope.headers, {value: $scope.chosen});
if (!_.isUndefined(header.mainId) && header !== chosenObject) {
return '\u00A0\u00A0' + header.value;
} else {
return header.value;
}
}
});
HTML here:
<div ng-app='myApp' ng-controller="ArrayController">
<br></br>
SELECT:
<select ng-model="chosen" ng-options="header.value as display(header) for header in headers">
</select>
</div>
There's yet another alternative with CSS and ng-class, fiddle here:
var app = angular.module('myApp', []);
app.controller('ArrayController', function ($scope) {
$scope.headers = [{
value: 'value 1'
}, {
value: 'value 2',
mainId: 12
}, {
value: 'value 3'
}, {
value: 'value 4',
mainId: 14
}, {
value: 'value 5'
}, {
value: 'value 6',
mainId: 18
}];
$scope.chosen = $scope.headers[0].value;
$scope.isIndented = function(header) {
var chosenObject = _.find($scope.headers, {value: header});
return !_.isUndefined(chosenObject.mainId);
};
});
app.filter('space', function() {
return function(text) {
if(_.isUndefined(text.mainId))
{
console.log('entered mainId');
return text.value;
}
else
{
console.log('entered');
return '\u00A0\u00A0' + text.value;
}
};
});
HTML:
<div ng-app='myApp' ng-controller="ArrayController">
<br></br>
SELECT:
<select ng-model="chosen" ng-options="header.value as (header | space) for header in headers" ng-class="{'indented-value': isIndented(chosen)}">
</select>
</div>
CSS:
.indented-value {
text-indent: -9px;
}
First off, this was a great question. I've unfortunately spent way too much time trying to come up with a solution to this. I've tried everything from CSS, to using ngModelController $formatters, to the solution (which isn't optimal as you'll see) I've posted below. Note, I do not think my solution deserves to be selected as the answer. It just "sorta" works, but like other solutions, it has a fatal flaw.
However, since your question was:
can anyone please tell me some solution to prevent the space to
display when selection
My official answer is:
No
There is no cross-browser way to get this working. No amount of CSS, jQuery, or Angular magic will make this work. While it may be disappointing, I think that is going to be the only correct answer to your question.
No one is going to be able to give you a solution that prevents the space from being displayed in the select box while maintaining it in the options that works reliably across browsers. Chrome and Firefox allow some amount of styling of elements in the select, options, and optgroup family, but nothing is consistent and works everywhere.
My best run at it is in this Plunk
It uses the fact that optgroup will do indentations for you, but it comes with terrible differences in how different browsers handle it. With some you can style away the problem, but others do not work (and never will). I'm posting it so maybe someone will be inspired and figure out a way to prove me wrong.
<body ng-app="app">
<div ng-app='myApp' ng-controller="ArrayController">
<div>{{selectedValue}}</div>
SELECT:
<select ng-model="selectedValue" >
<option indented="item.mainId" ng-repeat="item in headers">{{item.value}}</option>
</select>
</div>
</body>
(function() {
var app = angular.module('app', []);
app.controller('ArrayController', function($scope, $timeout) {
$scope.headers = [{
value: 'value 1'
}, {
value: 'value 2',
mainId: 12
}, {
value: 'value 3'
}, {
value: 'value 4',
mainId: 14
}, {
value: 'value 5'
}, {
value: 'value 6',
mainId: 18
}];
});
app.directive('indented', function($parse) {
return {
link:function(scope, element, attr){
if($parse(attr.indented)(scope)) {
var opt = angular.element('<optgroup></optgroup>');
element.after(opt).detach();
opt.append(element);
}
}
};
});
})();
If you opened the question up and allowed the implementation of a directive that mimicked the behavior of select but was instead built with li elements, then this would be trivial. But you simply can't do it with select.
Given your code, you can add one helper directive, to remove space in link function, once your option got selected.
As an example, add an id to your select, and directive
<select id="mySelect" option-without-space>
<option ng-repeat="(key, value) in headers">{{value | space}}
</option>
</select>
And directive might look like,
app.directive('optionWithoutSpace', () => {
return {
restrict: 'A',
link: function(scope, elem, attributes) {
var selectedOptionWithoutSpace = function () {
var selectedOption = $('#mySelect option:selected');
var optionText = selectedOption.text();
selectedOption.text(optionText.trim())
return false;
};
$(elem).on('change', selectedOptionWithoutSpace);
}
}
})
This is with a little help of jQuery, but I assume it is not a big problem.
Here is a fiddle.
Try this...
Change select box html following
<select ng-model="selectedOption" ng-options="item.value for item in headers"></select>
var app = angular.module('myApp', []);
app.controller('ArrayController', function ($scope) {
$scope.headers = [{
value: 'value 1'
}, {
value:'value 2',
mainId: 12
}, {
value: 'value 3'
}, {
value: 'value 4',
mainId: 14
}, {
value: 'value 5'
}, {
value: 'value 6',
mainId: 18
}];
$scope.selectedOption = $scope.headers[0]; //Add this line
});
app.filter('space', function() {
return function(text) {
if(_.isUndefined(text.mainId))
{
console.log('entered mainId');
return text.value;
}
else
{
console.log('entered');
return '\u00A0\u00A0' + text.value;
}
};
});
Related
I currently have a select in an angular app :
http://jsfiddle.net/4qKyx/251/
And I'm trying to manage my select depending on the number of result.
HTML
<div ng-controller="MyCtrl">
<select ng-model="form.type" required="required" ng-options="option.value as option.name for option in typeOptions" >
</select>
</div>
JS
var myApp = angular.module('myApp',[]);
function MyCtrl($scope) {
$scope.typeOptions = [
{ name: 'Feature', value: 'feature' },
{ name: 'Bug', value: 'bug' },
{ name: 'Enhancement', value: 'enhancement' }
];
if($scope.typeOptions.length == 1){
$scope.form = {type : $scope.typeOptions[0].value};
}else{
// first option set to "select an option" and null -> won't work with required
}
}
If I have only one element in my typeOptions, i want the only option to be pre-selected. Now if I have more than one element, I want an option saying "Select an option" but which can't be let selected in a required select. Thank you in advance for any help !
Can you try you controller code as like below,
var myApp = angular.module('myApp',[]);
function MyCtrl($scope) {
$scope.form = {};
$scope.typeOptions = [
{ name: 'Feature', value: 'feature' },
{ name: 'Bug', value: 'bug' },
{ name: 'Enhancement', value: 'enhancement' }
];
$scope.form.type=($scope.typeOptions.length===1) ? $scope.typeOptions[0].value : '';
}
also updated your jsfiddler
The code you've provided on SO works.
Your issue is only on the fiddler with the line
<option style="display:none" value="">select a type</option>
if you want your "placeholder" inside the select, you can do it like that :
if($scope.typeOptions.length == 1){
$scope.form = {type : $scope.typeOptions[0].value};
}else{
$scope.typeOptions.unshift( { name: 'Select a value', value: '' });
}
you can add option element to your select to be like
<select ng-model="" required
ng-options="option.value for option in typeOptions">
<option value=''>- Please Choose -</option>
</select>
and just do the check in you controller if the options.length equals 1 then set the ng-model the good thing is the required validation still works.
here is jsfiddle
if you removed the comment it show select option
I have dropdown selection menu & want to send the dropdown selected value in request params of api. My code is...
<select class="form-control" id = "SelectionInput_reason">
<option name="careerType" value="type_1">Career</option>
<option name="examType" value="type_2">Exams</option>
</select>
getValue = function() {
var selectedValue = this.value;
var selectedText = this.options[this.selectedIndex].getAttribute('name');
alert(selectedValue);
alert(selectedText);
}
document.getElementById('SelectionInput_reason').addEventListener('change', getValue );
Please give answer in angularJS if possible...
also how can I get the text input of tinymceeditor in a variable ?
$scope.tinymceModel = 'Initial content';
$scope.getContent = function() {
console.log('Editor content:', $scope.tinymceModel);
};
$scope.setContent = function() {
$scope.tinymceModel = 'Time: ' + (new Date());
};
$scope.tinymceOptions = {
selector: 'textarea',
//plugins: 'link image code',
toolbar: ' bold italic | undo redo | alignleft aligncenter alignright | code'
};
HTML is..
<div class="form-group">
<textarea ui-tinymce="tinymceOptions" id="jander" ng-model="tinymceModel" placeholder="Ask your question" class="form-control"></textarea>
</div>
Bind a model in your select dropdown. Like below
<select class="form-control" id = "SelectionInput_reason" data-ng-model="inputReason">
In your controller you will get selected option
console.log($scope.inputReason)
Here is a sample code with a fiddle attached
var myApp = angular.module('myApp', []);
myApp.controller('MyCtrl', function($scope) {
$scope.shelf = [{
'name': 'Banana',
'value': '$2'
}, {
'name': 'Apple',
'value': '$8'
}, {
'name': 'Pineapple',
'value': '$5'
}, {
'name': 'Blueberry',
'value': '$3'
}];
$scope.cart = {
'fruit': $scope.shelf[0]
};
});
<div ng-controller="MyCtrl">
<div>
Fruit List:
<select ng-model="cart.fruit" ng-options="state as state.name for state in shelf"></select>
<br/>
<tt>Cost & Fruit selected: {{cart.fruit}}</tt>
</div>
</div>
Fiddle link : http://jsfiddle.net/Td2NZ/1867/
My advise in this scenario is try to keep all input choices as a Js Object (Like $scope.shelf in this code) cause thats what Angular is built for rigid and robust handling of the data, eventually you could just load those options from a server or json file and not having to touch your HTML at all!
Hope this helps!
I am totally new to Bootstrap and angularjs world and I am stuck at this.
I have a simple select like this below
<div class="pull-left margin-left-20">
<select id="ddlPageSize" class="form-control form-ddl-adj"
ng-model="params.settings().countSelected"
ng-options="item.value as item.text for item in params.settings().countOptions"
ng-change="params.count(params.settings().countSelected)"></select>
</div>
In the controller, I have select values like this
var pageSizeList = [
{ value: 5, text: "5" },
{ value: 10, text: "10" },
{ value: 25, text: "25" },
{ value: 50, text: "50" },
{ value: 100, text: "100" }
];
5 is the option by default. Can some one tell me how to save user selection (say 10) in a cookie so that next time 10 should be the pagesize
You can use ngCookies module of AngularJS. You'll have to include angular-cookies.js in your code: https://code.angularjs.org/1.4.3/angular-cookies.min.js
Include ngCookies in your module declaration:
angular.module('testApp', ['ngCookies'])
Then you can save a cookie as:
$cookies.put('someKey', 'someVal');
You can retrieve a cookie as:
$cookies.get('someKey')
Updated:
Check this fiddle: http://jsfiddle.net/3xyf1bzo/
You can do this with ng-cookies
dropdown selection code html :
<div class="custom-param" ng-controller="themectrl">
<label id="default-lang" class="label">Default Theme:</label>
<select ng-change="themeChange(theme)" ng-model="theme" ng-options="theme.url as theme.name for theme in themes">
</select>
</div>
angularJS code :
var app = angular.module('themectrl', ['pascalprecht.translate','ngCookies'] );
app.controller('themeCtrl', function( $scope , $cookies ) {
$scope.theme = 'theme1.value';
// create the list of bootswatches
$scope.themes = [
{ name: 'Theme 1', url: 'theme1.value' },
{ name: 'Theme 2', url: 'theme2.value' }
];
// on dropdown change function
$scope.themeChange = function($selectedTheme) {
$cookies.put('ppcdfavtheme', $selectedTheme);
$scope.theme = $selectedTheme;
}
});
You can use Persistence Using local storage to save your data if you want I leave a link with working example Good luckAngularJS: Real Time Model Persistence Using Local Storage
I have a select box which is populated with some data from my controller. When an input value changes the contents of the select box should be filtered and a default value should be assigned based on the is default property of the data object.
Is there any way this can be done using angular directives or would it need to be done as a custom filter function doing something along the lines of
angular.forEach(vm.data,function(item){
if (vm.q == item.someId && item.isDefault) {
vm.result = item.value;
}
});
My html looks something like
<div ng-app="myApp" ng-controller="ctrl as vm">
<input type="text" ng-model="vm.q">
<select ng-options="item.value as item.description for item in vm.data | filter:{someId:vm.q}" ng-model="vm.result"></select>
</div>
and my controller looks like:
(function(){
angular.module('myApp',[]);
angular
.module('myApp')
.controller('ctrl',ctrl);
function ctrl()
{
var vm = this;
vm.data = [
{
someId: '1',
description: 'test1',
value: 100,
isDefault: true
},
{
someId: '2',
description: 'test2',
value: 200,
isDefault: false
},
{
someId: '3',
description: 'test3',
value: 100,
isDefault: true
},
];
}
})();
See my plunkr demo here: http://plnkr.co/edit/RDhQWQcHFMQJvwOyHI4r?p=preview
Desired behaviour:
1) Enter 1 into text box
2) List should be filtered to 2 items
3) Select box should pre-select item 1 based on property isDefault set to true
Thanks in advance
I'd suggest you include some 3rd party library, like lodash, into your project to make working with arrays/collections that much easier.
After that you could add ng-change directive for your input.
<input type="text" ng-model="vm.q" ng-change="vm.onChange(vm.q)">
And the actual onChange function in the controller
vm.onChange = function(id) {
var item = _.findWhere(vm.data, { someId: id, isDefault: true });
vm.result = item ? item.value : null;
};
And there you have it.
[ Please see updates at the bottom ]
I'm trying to make knockout depended selects, it's intended to make a "product" selection by these attributes, for example a product can have "size" and "material", if I selected "size", a knockout script make a request to the backend and retrieves which "material" available for the selected size, in other words, if an attribute is selected, other attributes are filtered out to show only available values ("all sizes": 1,2,3,4,5; "aluminium": 1,4).
Attributes list are completely dynamic, there are about 80 attributes which can be linked to the products in arbitrary way.
Are there any "best practices" for this situation?
I am trying to solve it with code like this, without success yet:
var ViewModel = function(data) {
var self = this;
self.data = data;
self.attributes = ko.observableArray();
self.data.forEach(function(item, i, a) {
// I passed .self to catch it later
// in products as view_model.attributes().
self.attributes.push(new VariableProduct(item, self));
})
};
var VariableProduct = function(item, view_model) {
var self = this;
self.attribute_name = ko.observable(item.name);
self.attribute_value = ko.observable('--');
// list of attribute values
self.attribute_values = ko.computed(function() {
var result = {};
view_model.attributes().forEach(function(attribute, i, a) {
// here I try to filter each attributes lists by values
// it doesn't work well
if (attribute.attribute_name() != self.attribute_name() && self.attribute_value() != '--') {
result = attribute.attribute_values().filter(
function(value) {
return value.indexOf(self.attribute_value()) >= 0;
});
}
});
return result;
});
};
UPDATE 1:
With Dnyanesh's reference to ko.subscribe(), i've achived these results, isn't ok yet, but a progress:
http://jsfiddle.net/xwild/65eq14p3/
UPDATE 2:
At the end it was solved with knockout.reactor and knockout.mapping plugins.
Related stackoverflow question with details and the answer.
For dependent select I think you can use subscribe in following manner
var vm = {
sizes: ko.observableArray([
{ name: 'size 1', id: 1},
{ name: 'size 2', id: 2},
{ name: 'size 3', id: 3},
{ name: 'size 4', id: 4}
]),
selectedSize : ko.observable(0),
};
vm.selectedSize.subscribe(function(newValue){
alert('Selected Size is ---> ' + newValue )
// Here at this point call your ajax or backend method and bind the values which are coming form
});
ko.applyBindings(vm);
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.0.0/knockout-min.js"></script>
<select data-bind="
options: sizes,
optionsText: 'name',
optionsValue: 'id',
value: selectedSize,
optionsCaption: 'Choose Size...'"">
</select>
<select data-bind="
options: material,
optionsText: 'name',
optionsValue: 'id',
value: selectedMaterial,
optionsCaption: 'Choose Material...'"">
</select>
I know I am talking about only part of solution to your problem but, I think you need to divide your data object to bind it to various controls.