I would like to use uib-popover to create a popup/tooltip for an option item generated by ng-options for a select box. I have tried two approaches but neither one is quite good enough. Ng-options works well because I have to have a default item selected, but I cannot figure out how to plug in uib-popover. If I use ng-repeat I feel like I have more control over how each option is generated, but I can't figure how to select a defualt item for that scenario. Here is the code I am using for the ng-repeat method:
(function() {
"use strict";
var selectionTestViewModel = function() {
var vm = this;
vm.options = [
{ id: 1, val: "Option 1", desc: "Description of Option 1" },
{ id: 2, val: "Option 2", desc: "Description of Option 2" }
];
vm.selectedOption = vm.options[0];
};
angular.module("angularApp").controller("selectionTestController", [selectionTestViewModel]);
}());
<div class="page-content" ng-controller="selectionTestController as st">
<h2>Selection Test</h2>
<div>
<select ng-model="st.selectedOption">
<option ng-repeat="op in st.options track by op.id" value="{{op.id}}" title="{{op.desc}}">{{op.val}}</option>
</select>
<div>
<span>Selected Value: {{st.selectedOption}}</span>
</div>
</div>
</div>
Related
I am trying to bind the dropdown . following code works
<select data-bind="options :MyArray"/>
However it doesn't works but when i add the Knockout bindings (as below) .the dropdown doesn't shows up
<select data-bind="options: MyArray, event:{change:DropdownChnaged.bind($data,'Task')} "/>
It looks as though you have a typo in your change event (DropdownChnaged -> DropdownChanged). That maybe the root cause of the issue.
But I would also avoid using the change event and instead use knockouts subscriber functionality.
When the dropdown value is being set, you can subscribe to the value and execute a function when the observable value is updated. I have provided a snippet below which should demonstrate how you can use this.
var VM = function() {
this.MyArray = [
{
text: "Item A",
data: "This is the description for Item A",
otherData: { myData: 'MyOtherDataA'}
},
{
text: "Item B",
data: "Description of Item B",
otherData: { myData: 'MyOtherDataB'}
},
{
text: "Item C",
data: "This is Item C's description",
otherData: { myData: 'MyOtherDataC'}
}
];
this.selectedItem = ko.observable();
this.selectedItem.subscribe(function(latest)
{
console.log("Change event triggered");
console.log(latest);
}, this);
};
ko.applyBindings(new VM());
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.2/knockout-min.js"></script>
<select data-bind="value: selectedItem, options: MyArray, optionsText: 'text'">
</select>
<!-- ko with: selectedItem -->
<p>
Item Description: <span data-bind="text: data"></span>
</p>
<!-- /ko -->
So I love Semantic UI and I just started working with Vue.js
Semantic UI dropdowns must be initialized using the dropdown() in semantic.js, it generates a complex div based HTML to show the dropdowns in a pretty way.
The problem comes when I bind Vue to a dropdown, it doesn't update the UI according to the model. Especially when I change the value of the parent dropdown.
For some reason the bidning works fine the first time an item is selected on the parent dropdown, but not after that :|
<div class="ui grid">
<div class="row">
<div class="column">
<div class="ui label">Vechicle Make</div>
<select class="ui dropdown" v-model="selected" id="vehicle-makes" v-on:change="onChange">
<option v-for="option in options" v-bind:value="option.id">
{{option.text}}
</option>
</select>
</div>
</div>
<div class="row">
<div class="column">
<div class="ui label">Vechicle Model</div>
<select class="ui dropdown" v-model="selected" id="vehicle-models">
<option v-for="option in options" v-bind:value="option.id">
{{option.text}}
</option>
</select>
</div>
</div>
</div>
var model_options = {
1: [{ text: "Accord", id: 1 }, { text: "Civic", id: 2 }],
2: [{ text: "Corolla", id: 3 }, { text: "Hi Ace", id: 4 }],
3: [{ text: "Altima", id: 5 }, { text: "Zuke", id: 6 }],
4: [{ text: "Alto", id: 7 }, { text: "Swift", id: 8 }]
};
var makes_options = [
{ text: "Honda", id: 1 },
{ text: "Toyota", id: 2 },
{ text: "Nissan", id: 3 },
{ text: "Suzuki", id: 4 }
];
var vm_makes = new Vue({
el: "#vehicle-makes",
data: {
selected: null,
options: makes_options
},
methods: {
onChange: function(event) {
vm_models.selected = null;
vm_models.options.splice(0);
for (index = 0; index < model_options[this.selected].length; index++) {
vm_models.options.push(model_options[this.selected][index]);
}
}
}
});
var vm_models = new Vue({
el: "#vehicle-models",
data: {
selected: null,
options: []
}
});
// Eveything works fine if I remove this...
$('.ui.dropdown').dropdown();
The exact code can be found here. https://codepen.io/adnanshussain/pen/KqVxXL?editors=1010
You are using a v-for directive on your option element without a key attribute. Without this key, Vue uses an "in-place patch" strategy to optimize rendering. This is most likely messing with what your Semantic UI dropdown is expecting as far as changes to the select element go.
Add a key attribute to your option tag, providing a unique id as the value:
<option v-for="option in options" :value="option.id" :key="option.id">
{{ option.text }}
</option>
To clear the value in the model's select element when the make changes, you can use $('#vehicle-models').dropdown('restore defaults').
Also, if you put all the logic in one Vue instance, things become a lot simpler: Here's an example codepen.
I am working with angular and semantic ui. I am trying to make a selection of Y and N through a select option. Basically i just want the first item was selected when the page show up. Tried many ways but i couldn't make it works.
Please take a look at this plunker.
angular.module('myapp', [])
.controller('testctrl', function ($scope){
$scope.add = {};
$scope.Consigns = [{value: 'N',label: 'N'}, {value: 'Y',label: 'Y'}];
$scope.add.consign = $scope.Consigns[0].label;
})
.controller('testctrl1', function ($scope){
$scope.add = {};
$scope.Consigns1 = [{value: 'N',label: 'N'}, {value: 'Y',label: 'Y'}];
$scope.add.consign1 = $scope.Consigns1[0].label;
});
https://plnkr.co/edit/cHcLd14xKFxLMS4uy0BM?p=preview
Print the model value in default placeholder. Rather than sending the label value in $scope.add.consign you could send the whole object and print whats required.
Working plunker: https://plnkr.co/edit/XeuiS7p3K1OOx5nHL9c5?p=preview
javascript:
$scope.ListOrder =
[
{ Name: "price", Id: 1 },
{ Name: "exist", Id: 2 },
{ Name: "Sale", Id: 3 },
{ Name: "New", Id: 4 }
];
$scope.Order = { Name: "exist", Id: 1 };
HTML:
<select ng-model="Order" ng-options="obj.Name for obj in ListOrder"></select>
Remove
<script>
$('.ui.dropdown').dropdown();
</script>
and also change select tag to this
<select ng-model="add.consign" class="ui fluid dropdown" ng-options="x.label as x.label for x in Consigns">
<option value=""></option>
</select>
im trying to get my second dropdownlist to work, but cant figure out what is the problem. The first one is showing the data, byt the second is not working.
html:
<select class="form-control"
ng-options="option as option.label for option in myCtrl.options track by option._id"
ng-model="myCtrl.selected"></select>
<select ng-disabled="!myCtrl.selected" class="form-control">
<option ng-repeat="child in myCtrl.options">#{{child.childs}}</option>
</select>
JS:
var vm = this;
vm.options = {};
//get populate data for cascading options
$http.get("data/support.json").success(function(response){
vm.options = response;
vm.selected = vm.options[0];
});
support.json
[{
"_id": "1",
"label": "Title 1",
"childs": [
"Title 1 - sub 1",
"Title 1 - sub 2"
]
},
{
"_id": "2",
"label": "Title 2",
"childs": [
"Title 2 - sub 1",
"Title 2 - sub 2"
]
}]
The second one should be
<option ng-repeat="child in myCtrl.selected.childs">{{child}}</option>
If you are trying to display the children of the selected parent option.
Also, your first select can have its options simplified to
ng-options="option.label for option in myCtrl.options track by option._id"
Scenario: I make a request to the server for a part. It gives me this back (it's pseudo, but represents what I'm looking at):
{
PartNumber : "XYZ",
Description: "ABCFOO",
ProductClass: "Widget",
FieldList:[
{Name: "PROGRAM TYPE", Value: "Program3"},
{Name: "SHIP", Value: false},
{Name: "NOTES", Value: "SomeValue1"}
],
MoreStuff : [{
...
}]
}
Note the FieldList list of elements, that's the focus here.
The server also gave me a list of certain fields, their types and default values. It looks like this:
[
{FieldName : "PROGRAM TYPE", FieldType: "List", Defaults: [{Name:"Program 1", Value: "Program1"},{Name:"Program 2", Value: "Program2"},{Name:"Program 3", Value: "Program3"}]},
{FieldName : "SHIP", FieldType : "Boolean", Defaults: []},
{FieldName : "NOTES", FieldType: "TextArea", Defaults: []}
]
That comes in a seperate REST call, and the prior to loading my Part. I use it to create part of the HTML page for the Part. You can see they're similarly related to the FieldList section from when I ask for Part.
From that "list of fields" and defaults -- I generate the appropriate HTML elements on the page. If it's a Boolean field type, I create a checkbox - if it's a list, I create a SELECT (with options given in Defaults), TextArea is a text-area, etc. That all works fine. It ends up looking like:
<input data-bind="textInput: PartNumber"/>
<textarea data-bind="textInput: Description"></textarea>
<!-- generating fieldlist - i create a pseudo attr because the field name can have spaces-->
<select field_label="PROGRAM TYPE"> <!-- how the heck do i bind to this??-->
<option value="Program1">Program 1</option>
<option value="Program2">Program 2</option>
<option value="Program3">Program 3</option>
</select >
<input type="checkbox" field_label="SHIP" value="true"/> <!-- or this, how to bind to it?!-->
<!-- end of field list generation -->
Now I take the object (the part I'm given) and put that into my ViewModel - that is all working just swimmingly. I make it easy and just use ko.mapping.fromJS(rest_data); Works just fine.
Data binding is ducky -- for what I am able to bind it to. My issue comes from -- how the heck do I map my FieldList to the HTML I generated for the fields the server gave me?. My data / my viewmodel object has FieldList in it, with a buncha stuff I want to map to that generated stuff. The only real "key" I have is the self-created field_label I have, because the server's FieldName can have spaces.
So I guess what I'm asking is, I have that array of FieldList from my part. I have the whole Part object in my view model and it's all fine. How do I take that FieldList and map it into my self-generated set of fields from the other object (ie., take the FieldList name and tie it to the element with field_label of the same value?)
Spelled out - it'd be like: How to map FieldList with Name of "PROGRAM TYPE" to HTML element having field_label of "PROGRAM TYPE".
I begin to think something like this might be the direction I should be going:
http://jsfiddle.net/MhdZp/128/
but it goes over my head.
One way to approach this:
function Option(definition) {
this.definition = definition;
this.value = ko.observable();
this.templateName = 'input-template-' + definition.FieldType;
}
function ViewModel() {
var self = this;
// from REST call
var fieldDefinition = [{
FieldName: "PROGRAM TYPE",
FieldType: "List",
Defaults: [
{ Name: "Program 1", Value: "Program1" },
{ Name: "Program 2", Value: "Program2" },
{ Name: "Program 3", Value: "Program3" }
]
}];
self.options = ko.observableArray();
// for the sake of the example
self.options.push(new Option(fieldDefinition[0]));
// methods
self.optionByName = function (name) {
return ko.utils.arrayFirst(self.options(), function (option) {
return option.Name = name;
});
};
// poor man's init, imagine 2nd rest call instead
self.optionByName("PROGRAM TYPE").value("Program3");
}
and
<script type="text/html" id="input-template-List">
<label data-bind="text: definition.FieldName"></label>
<select data-bind="
value: value,
options: definition.Defaults,
optionsText: 'Name',
optionsValue: 'Value',
optionsCaption: 'Please select...'
"></select>
</script>
and
<div data-bind="foreach: options">
<div data-bind="template: templateName"></div>
</div>
Add more templates as needed, this should be very easy to extend.
jsFiddle: http://jsfiddle.net/0nxt2zte/