I'd like to create a CompositeView that contains a dropdown-list from a collection:
my views:
var ItemView = Backbone.Marionette.ItemView.extend({
template: '#item-tpl'
});
var CompositeView = Backbone.Marionette.CompositeView.extend({
template: '#comp-tpl',
itemView: ItemView,
itemViewContainer: '#mySelect'
});
my templates:
<script id = "item-tpl" type="text/template">
<option value="<%= id %>"><%= name %></option>
</script>
<script id = "comp-tpl" type="text/template">
...
<form>
<div class="control-group">
<select id='mySelect'></select>
</div>
</form>
...
</script>
the rendered HTML displays the default div's, which break the options list
<select id="mySelect">
<div>
<option value="5">name 1</option>
</div>
<div>
<option value="6">name 2</option>
</div>
</select>
how can I achieve this:
<select id="mySelect">
<option value="5">name 1</option>
<option value="6">name 2</option>
</select>
I would use this technique: http://jsfiddle.net/c9Lrm/8/
Start by simplifying your template:
<script id = "item-tpl" type="text/template">
<%= name %>
</script>
Then, you need to provide the information about the item view so it renders with the data you want:
var aItemView = Backbone.Marionette.ItemView.extend({
template: '#item-tpl',
tagName: "option",
onRender: function(){
this.$el.attr('value', this.model.get('id'));
}
});
You specify the tagName attribute so it doesn't get rendered with the default div tag but uses the option tag you need. Then, when the option gets rendered, you need to set the value attribute, which you do with the onRender function.
Finally, here's your new composite view:
var aCompositeView = Backbone.Marionette.CompositeView.extend({
template: '#comp-tpl',
itemView: aItemView,
itemViewContainer: "select"
});
We specify the itemViewContainer to tell Marionette where to put our item views. That way, there's no need for us to redefine appendHtml.
This solution is a lot cleaner, since we're using Marionette functionality instead of doing everything on our own... But of course, the other solutions will work also.
If you want to learn more about generating the proper HTML structure with Marionette, you might be interested in this blog post of mine: http://davidsulc.com/blog/2013/02/03/tutorial-nested-views-using-backbone-marionettes-compositeview/
Is pretty easy actually the only thing you need to do is wrap the "el" (element) with jquery so the view should look like this:
var aItemView = Backbone.Marionette.ItemView.extend({
..
..
el: $('#mySelect'),
..
that avoid the default div and you can use only the elements you need.
so will get this instead
<select id="mySelect">
<option value="5">name 1</option>
<option value="6">name 2</option>
</select>
Related
I have a form with with option list
<form class="column-form">
<select id="classSelection" ng-change="classOptionChange()" ng-model="selectedClass" maxHeight="120">
<option selected value="">{{classOptions}}</option>
</select>
</form>
Sample class options is here
[{"id":"classR","text":" Color - Red"},{"id":"classG","text":"Color - Green"}, {"id":"classY","text":"Color - Yellow"}]
My directive is simple as I'm just trying to print out the value of my selected option. However, it's always null.
(function() {
appModule.directive('classDefault', [ '$translate', '$timeout', '$window', classService, function($translate, $timeout, $window, $document, classService) {
return {
restrict : 'E',
scope : {
.......
}
link : function(scope, element) {
scope.classOptionChange() = function() {
console.log(scope.selectedClass);
Any suggestions?
UPDATE - Thanks for all the suggestions below. Apparently, we are using this widget that supposed to render the option lists and then bind to the select tag but it is currently broken.
You need to bind the array to the select tag. One option to do so is to use the NgOptions directive.
Here's an working example
angular.module("app",[]).controller("ctrl", function($scope){
$scope.items = [{"id":"classR","text":" Color - Red"},{"id":"classG","text":"Color - Green"}, {"id":"classY","text":"Color - Yellow"}];
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.10/angular.min.js"></script>
<div ng-app="app" ng-controller="ctrl">
<select ng-change="classOptionChange()"
ng-model="selectedClass"
maxHeight="120"
ng-options="item as item.text for item in items">
</select>
<h3>{{selectedClass}}</h3>
</div>
It seems like you are not properly rendering all options that have been passed down to your directive. Ideally you should loop over the classOptions collection using ng-repeat/ng-options directive and render the select tag filled option's. And then specify ng-value-"opt" on each of your option element. That will basically help you assign whole option object to selectedClass ng-model.
Template
<form class="column-form">
<select id="classSelection"
ng-change="classOptionChange()" ng-model="selectedClass"
maxHeight="120">
<option selected value="">Select option</option>
<option ng-value="opt" ng-repeat="opt in classOptions">{{opt.text}}</option>
</select>
</form>
Demo Plunker
I am creating a select tag in angular. According to many sites I have read and some posts on here, it says when using the select tag to not use "ng-repeat" on the option tag but use "ng-options" on the select tag so that is how I set it up. My question is, I want a specific option tag selected by default, how do i set the selected attribute using this method?
<select class="form-control" ng-model="selected_group" ng-change="new_group($event)" ng-options="group as (group.group_name | decodeuri) for group in groups"></select>
Choosing a default is easy: set selected_group equal to a particular group in your controller.
The basic idea is that you have a collection and the selected option is to be stored in your ng-model. To designate a selection from the start, you need to put something in ng-model. That would have to be in your controller.
You could add an <option> tag:
<select class="form-control" ng-model="selected_group" ng-change="new_group(selected_group)" ng-options="group as (group.group_name | decodeuri) for group in groups">
<option value="">Please Select an Option</option>
</select>
Here I have created small working demo
<div ng-app="myApp" ng-controller="myCtrl">
<select class="form-control" ng-model="option.group" ng-options="group as (group.name | myfilter) for group in groups">
</select>
</div>
var app = angular.module('myApp', []);
app.filter('myfilter', function() {
return function(v) {
return v == 'test3' ? 'filtered test3' : v;
};
});
app.controller('myCtrl', function($scope) {
$scope.groups = [{id:1,name:'test1', phone:'1234567890'},
{id:2,name:'test2', phone:'1234567890'},
{id:3,name:'test3', phone:'1234567890'}
];
$scope.option={
group: $scope.groups[1]
}
});
Please see this relevant jsFiddle
Within the code I am trying to fire a method when a different option is selected to alert the user. However no event is being trigged
HTML:
<div ng-controller = "MyCtrl">
<p>Term</p>
<select id = "term" ng-change="test()">
<option value="5">5</option>
<option value="10">10</option>
<option value="15">15</option>
</select>
</div>
JS:
var app = angular.module('HelloApp', []);
app.controller('MyCtrl',['$scope','$element', function($scope, $element) {
$scope.test = function () {
alert ("changed!");
}
}]);
You have some issues.
Firstly: <div ng-controller = "MyCtrl"> - you have spaces in between.
Secondly, you're not declaring your app with ng-app. This is because you set your fiddle as jquery, and not Angular. If you had set it as angular you wouldn't need this in the fiddle
This is your fiddle setup
This is an Angular fiddle setup
Thirdly, to use select with AngularJS, you need to have an ng-model on the select tag. In this case i just used bob
<div ng-app="HelloApp"> <!-- declare your angular app. typically would go on body or html -->
<div ng-controller="MyCtrl">
<p>Term</p>
<select ng-model="bob" ng-change="test()">
<option value="5">5</option>
<option value="10">10</option>
<option value="15">15</option>
</select>
</div>
</div>
var app = angular.module('HelloApp', []);
app.controller('MyCtrl',['$scope','$element', function($scope, $element) {
console.log('ctrl working');
$scope.test = function () {
alert ("changed!");
}
}]);
Here is a working fiddle
http://jsfiddle.net/ctbLparv/
Also, if your intention is to just set a property based on the selection, you don't need to use ng-change. You can rely on the two-way binding.
So for example, this fiddle: http://jsfiddle.net/ps8jnyL8/
No select is being called. We also default the selected term to 10 when it first loads.
<div ng-app="HelloApp">
<div ng-controller="MyCtrl">
<p>Term</p>
<select ng-init="selectedTerm = '10'" ng-model="selectedTerm">
<option value="5">5</option>
<option value="10">10</option>
<option value="15">15</option>
</select>
<p>Selected Term: {{selectedTerm}}</p>
</div>
</div>
Here is the working JSFiddle:
https://jsfiddle.net/G8S32/1162/
The main change was adding this line:
ng-model="items"
which doesn't do anything except update the model and cause the event to fire.
Check out the documentation for ng-change:
https://docs.angularjs.org/api/ng/directive/ngChange
Particularly this line:
The ngChange expression is only evaluated when a change in the input
value causes a new value to be committed to the model.
I have the issue with Angular.js v1.3.11 and ng-options directive. The problem is next. I have a model value I know ahead but data for binding of options comes in AJAX request later and Angular.js produces that as two selected options: with my value and first one.
Html
<body ng-controller="MainCtrl">
<select ng-model="selectedYear" ng-options="o.year as o.year for o in options"></select>
</body>
Javascript
var app = angular.module('plunker', []);
app.controller('MainCtrl', function($scope, $timeout) {
$scope.selectedYear = 2013;
$scope.options = [];
$timeout(function() {
$scope.options = [{year: 2012}, {year: 2013}, {year: 2014}];
});
});
Output
<select ng-model="selectedYear" ng-options="o.year as o.year for o in options" class="ng-pristine ng-valid ng-touched">
<option value="0" selected="selected" label="2012">2012</option>
<option value="1" selected="selected" label="2013">2013</option>
<option value="2" label="2014">2014</option>
</select>
Plunker
http://plnkr.co/edit/gFZ8Z7T5DhDPvk4G9tEU?p=preview
If you use "track by" then you can leave the $scope.selectedYear outside the $timeout callback function. You shouldn't really worry about the selected attribute. Change your code to include "track by o.year" and remove the "select as" part:
<select ng-model="selectedYear" ng-options="o.year for o in options track by o.year"></select>
Also in your controller you can set the predefined selectedYear like below to the object.
$scope.selectedYear = {year: 2013};
Here is a working plnkr:
http://plnkr.co/edit/UMfEIWlBwBnyj9wQ1FEx?p=preview
I have been experiencing this same issue. I used your plunker and updated the bits to 1.4 RC2. Be careful because this is a Release Candidate and is a pre-release.
Here is the working plunker http://plnkr.co/edit/UVL3dxYy0PNRcXuXG5y0?p=preview
<script data-require="angular.js#1.3.x" src="https://code.angularjs.org/1.4.0-rc.2/angular.js" data-semver="1.4.0-rc.2"></script>
This is a confirmed bug in 1.3 that no longer exists in 1.4. More information can be found here.
I have a following question for AngularJS. I have a
select with options created with ngOptions. I want to
set selected option back to default option. I tried to
delete model variable e.g:
if(angular.isDefined($scope.first)){
delete $scope.first;
}
But this not working. Here is my html.
<div ng-app="app">
<div ng-controller="testCtrl">
<select data-ng-model="first" data-ng-options="item.name for item in selectContent" required="required">
<option value="" style="display: none;">-- select --</option>
</select>
{{first.value}}
<hr/>
<input type="button" value="reset dropdown" data-ng-click="resetDropDown()"/>
</div>
</div>
And here is my JavaScript code:
angular.module('app', []).controller('testCtrl', function ($scope) {
$scope.selectContent = [
{
name: "first",
value: "1"
},
{
name: "second",
value: "2"
}
];
$scope.resetDropDown = function() {
if(angular.isDefined($scope.first)){
delete $scope.first;
}
}
});
Here is working jsfiddle:
http://jsfiddle.net/zono/rzJ2w/
How I can solve this problem?
Best regards.
Your reset-button is placed outside of the div containing your controller. This means that your reset-function does not exist in the context where you try to use it.
Change to:
<div ng-app="app">
<div ng-controller="testCtrl">
<select data-ng-model="first" data-ng-options="item.name for item in selectContent" required="required">
<option value="" style="display: none;">-- select --</option>
</select>
{{first.value}}
<hr/>
<input type="button" value="reset dropdown" data-ng-click="resetDropDown()"/>
</div>
</div>
It's always a good idea to use a debugger to make sure the code you're trying to fix is actually being executed.
$scope.resetDropDown = function() {
$scope.first = "";
}
Solution above works for Windows and Android, but did not work for iOS browsers. Probably events are happening in different order there.
So for my code I:
created ID for select element, so I could easily find it by
iQuery;
created delayed invocation of to statements to ensure the
reset is happenning at the very end;
and just in case was
resetting in two ways (but just first way was actually enough in iOS
too);
function resetDropDown () {
$timeout(function(){
$scope.first = '';
// jQuery way
$('select#idOfSelectElement option:first' ).prop( 'selected', true );
}, 200);
}