How to create a tooltip for angular option using ng-options - javascript

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

Knockup.js dropdown not working after adding KO binding

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 -->

Vue.js not working with Semantic UI dropdown

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.

Angularjs Select Option set to first item did not work

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>

Cascading dropdownlist angularjs

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"

Knockout : Unusual Mapping Pattern

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/

Categories