I have a dropdown with various versions. For the first version, I'd like to add "latest" to the displayed text on the dropdown only, is there a simple way to do that?
HTML:
<select ng-model='selectedVersion'
ng-options="version.name for version in versions"
class="form-control">
</select>
JS:
$scope.versions = [
{ name: "3.0" },
{ name: "2.0" },
{ name: "1.0" },
]
$scope.selectedVersion = $scope.versions[0];
So right now the dropdown shows "3.0", "2.0", "1.0", but I would like to have the first option be "3.0 (latest)".
I can change the object name directly, but I'm passing the selected object to another scope and would cause issues, so this won't be stable:
$scope.versions[0].name += " (latest)";
I just want "latest" to be show inside the dropdown if possible. Thanks!
If your array is always going to have latest first, you can do this:
<select ng-model='selectedVersion'
ng-options="(version.name == versions[0].name ? 'latest' : version.name) for version in versions"
class="form-control">
</select>
Is better wraps into a namespace for avoid problems between scopes
js
function MyCntrl($scope) {
var versions = [{ name: "3.0" }, { name: "2.0" }, { name: "1.0" },];
$scope.prop = {
"value": versions[0],
"values": versions
};
}
html
<div ng-controller="MyCntrl">
<select ng-model="prop.value" ng-options="v.name for v in prop.values">
</select>
</div>
Preview
Related
so i was trying to make a button that when clicked it copy a value from a variable
like
<button onclick="copyToClipboard()">COPY</button>
and then on that function it takes the element to copy from a variable like
var copyids = {
"ids": [
{
"name": "id1",
"id": 192389021
},
{
"name": "id2",
"id": 123879032
},
{
"name": "id3",
"id": 149018292
},
]
};
so like copyids.ids[0].id and it copy that value
i hope its understandable
Maybe this helps
function copyToClipboard() {
let temp = document.createElement('textarea');
temp.value = copyids.ids[0].id;
document.body.appendChild(temp);
temp.select();
document.execCommand('copy');
document.body.removeChild(temp);
}
To copy, you will need to select before what you want to copy. Maybe you should put the data of the variable somewhere and copy it.
https://www.w3schools.com/howto/howto_js_copy_clipboard.asp
I made you a solution with the ability to select the desired data cell from the array. I've added a select tag for you, listing the name of each cell.
And at the choice of a specific option with you copy id in accordance with the specified name.
function copyToClipboard() {
var copyids = {
ids: [
{
name: "id1",
id: 192389021,
},
{
name: "id2",
id: 123879032,
},
{
name: "id3",
id: 149018292,
},
],
};
let selectIndex = document.querySelector("select").selectedIndex;
let storage = document.createElement("input");
storage.value = copyids.ids[selectIndex].id;
console.log(storage.value);
document.body.appendChild(storage);
storage.select();
document.execCommand("copy");
document.body.removeChild(storage);
}
<button onclick="copyToClipboard()">COPY</button>
<select>
<option value="id1">id1</option>
<option value="id2">id2</option>
<option value="id3">id3</option>
</select>
The execCommand method has been deprecated, and it might not be supported by newer releases.
However, there is a Clipboard API that you can use in it's place.
To let the user select what to copy from your list:
<button onclick="copyToClipboard()">COPY</button>
<select>
<option value="id1">id1</option>
<option value="id2">id2</option>
<option value="id3">id3</option>
</select>
Then your function can work like this:
function copyToClipboard() {
var copyids = {
ids: [
{
name: "id1",
id: 192389021,
},
{
name: "id2",
id: 123879032,
},
{
name: "id3",
id: 149018292,
},
],
};
let selectedIndex = document.querySelector("select").selectedIndex;
navigator.clipboard.writeText(copyids[selectedIndex].name);
Im very new to JS and OJET. I'm using oracle jet to create a form. I need to create two select fields, the firts displays a client's name and the next one must change is values with the selected client's team members.
I have a JSON File with this format:
{
"clients": [
{
"id": "C01",
"name": "Client 1",
"manager": "Manager 1",
"team": [
{
"id": "C1MEM1",
"name": "member 1"
},
{
"id": "C1MEM2",
"name": "member 2"
},
{
"id": "C1MEM3",
"name": "member 3"
},
{
"id": "C1MEM4",
"name": "Member 4"
}
]
},
{
"id": "C02",
"name": "Client 2",
"manager": "Manager 2",
"team": [
{
"id": "C2MEM1",
"name": "member 1"
},
{
"id": "C2MEM2",
"name": "member 2"
},
{
"id": "C2MEM3",
"name": "member 3"
},
{
"id": "C2MEM4",
"name": "member 4"
}
]
}
I managed to create a select field with the clients name:
self.clientsListVal = ko.observableArray(['C01']);
self.clientsList = ko.observableArray();
$.getJSON("http://localhost:8000/js/json/clients.json").
then(function(data){
$.each(data["clients"],function(){
self.clientsList.push({
value: this.id,
label: this.name
});
});
});
Then I tried to get the next select fields this way, but it doesn't work :( :
self.memberList = ko.observableArray();
$.getJSON("http://localhost:8000/js/json/clients.json").
then(function(data){
$.each(data["clients"],function(){
if (this.id === self.clientsListVal ) {
$.each(this["team"], function(){
self.memberList.push({
value: this.id,
label: this.name
});
});
}
});
});
This is the HTML im using:
<div class="oj-applayout-content">
<div role="main" class="oj-hybrid-applayout-content">
<div class="oj-hybrid-padding">
<h3>Dashboard Content Area</h3>
<div>
<label for="clients">Clients</label>
<select id="clients"
data-bind="ojComponent:
{component: 'ojSelect',
options: clientsList,
value: clientsListVal,
rootAttributes: {style:'max-width:20em'}}">
</select>
<label for="select-value">Current selected value is</label>
<span id="select-value" data-bind="text: clientsListVal"></span>
<label for="members">Members</label>
<select id="members"
data-bind="ojComponent: {component: 'ojSelect',
options: memberList,
value: memberListVal,
rootAttributes: {style:'max-width:20em'}}">
</select>
</div>
</div>
</div>
Any help or hint? thank you!.
EDIT:
I think the problem is that self.clientsListVal is returning a function not the current selected value. I added console.log(self.clientsListVal) to the view model to see the current value.
If I change self.clientsListVal for a string:
if(this.id === 'C01'){}
I get the members of the client "C01".
I tried changing self.clientsListVal to $('#clients').val(), this is the id of the select input and i get undefined in the console.log.
How can I get the select field string value inside the viewmodel?
In Knockout, observables are functions -- so when you ask for the observable directly, like self.clientsListVal, you get the function definition. To get the underlying value, call the observable like a function: self.clientsListVal().
So your test becomes if (this.id === self.clientsListVal() ) {
Now you have another problem -- the observable holds an array, not an ID. The array may have a single ID element in it, but you have to reach into the array to get it.
Since you didn't show us how a value gets into clientsListVal, it's hard to say what you need to do. Is it bound to an input field where the user specifies a value? Is it populated from a data call? either way, do you ever need to have more than one ID in clientsListVal? If you only need to hold one ID at a time, change clientsListVal from an observableArray to a simple observable and your test will work.
If clientsListVal can hold multiple values, you'll need to loop over them. There are various ways to do this. You can get the underlying array by assigning the value of the observableArray to a variable: var clients = clientsListVal(). clients now holds the array, and you can use jQuery's $.each, the native Array.each, or some other way to loop over or map the array. Or you can use Knockout's built-in array utilities, like arrayForEach
if you don't want to change to a regular observable but expect the array to only have a single element, you can get at it like clientsListVal()[0] -- that's the 0th (first) element of the array. Watch out for empty arrays, tho.
I'm having the angular feature issue where my select list has an empty first option, but this situation is a little different from the research I've done online. When I place the select tag outside of the ng-repeat, there is no blank option as the default selected value. When I place the select tag using the ng-option attribute within the ng-repeat, I have the blank issue. I've tried setting the default value for the ng-model attribute on the select tag with no luck. Here is the html fragment:
<tr ng-repeat="item in todo.items">
<td>{{item.project}}</td>
<td>{{item.action}}</td>
<td>
<select ng-model="ttdSelect" ng-change="moveItem(item.id, ttdSelect);" ng-options="option.name for option in todo.options track by option.name">
</select>
</td>
</tr>
javascript:
var items = [{"id" : 1, "name" : "ttd" , "action" : "do it"}];
var selectOptions = [{ "name" : "next", "value" : "nextUp"},
{ "name" : "in progress", "value" : "inProgress"},
{ "name" : "waiting", "value" : "waiting"},
{ "name" : "done", "value" : "done"},
{ "name" : "trash", "value" : "trash"}];
app.controller("appController", function ($scope)
{
$scope.todo.items = items;
$scope.todo.options = selectOptions;
}
Similar to the answer of jusopi but here in a SO snippet:
var app = angular.module('myApp', []);
var items = [{
"id": 1,
"name": "ttd",
"action": "do it"
},
{
"id": 2,
"name": "zzz",
"action": "do it 2"
}];
var selectOptions = [{
"name": "next",
"value": "nextUp"
}, {
"name": "in progress",
"value": "inProgress"
}, {
"name": "waiting",
"value": "waiting"
}, {
"name": "done",
"value": "done"
}, {
"name": "trash",
"value": "trash"
}];
app.controller("appController", function($scope) {
$scope.todo = {};
$scope.todo.items = items;
$scope.todo.options = selectOptions;
angular.forEach($scope.todo.items, function(item, key) {
item.ttdSelect = $scope.todo.options[0];
});
});
<!DOCTYPE html>
<html ng-app="myApp">
<head>
<meta charset="utf-8" />
<script data-require="angular.js#1.4.x" src="https://code.angularjs.org/1.4.8/angular.js" data-semver="1.4.8"></script>
<script src="app.js"></script>
</head>
<body ng-controller="appController">
<div>
<table class="table">
<tr ng-repeat="item in todo.items">
<td>{{item.project}}</td>
<td>{{item.action}}</td>
<td>
<select ng-model="item.ttdSelect"
ng-change="moveItem(item.id, item.ttdSelect);"
ng-options="option.name for option in todo.options track by option.name">
</select>
</td>
</tr>
</table>
<b>Trace:</b>
<pre>
items = {{todo.items | json}}
</pre>
<pre>
options = {{todo.options | json}}
</pre>
</div>
</body>
</html>
I had a hard time following what exactly it is that you wanted so I tried to do it the way I'd normally tackle a problem like this.
example - http://codepen.io/jusopi/pen/PZzxPY
There are a few problems I addressed in reworking your code:
ttdSelect was not pointing to anything in your code. I assumed you meant to update the status value of the todo item so I assigned it to item.status
I created a status option to match a falsy value when a todo item doesn't have a current status
I demonstrated that you can actually bypass ng-options on the <select> and instead use ng-repeat on the <option> element instead to make it a little easier to read.
I hope this helps. Keep in mind I did this in jade/coffeescript because I work faster and better that way. You can easily see the compiled html/js if you need to.
So the overview of the problem; I am retrieving data from an api and creating a CRUD page for it. The data has a set of labels that the user can select.
Below is a code sample representing my problem. The labels selected by the user are represented by the user.labels relationship and the total available labels that can be selected are represented by user.parent.grandparent.labels.
I'm able to sync the selection. What I can't seem to figure out is how to get rid of options that have already been selected from the list of options on any other subsequent select field.
angular.module('app', [])
.controller('select', ['$scope', '$filter', '$location',
function($scope, $filter, $location) {
$scope.user = {
"parent": {
"grandparent": {
"labels": [{
"id": 28,
"name": "Label 1",
}, {
"id": 17,
"name": "Label 2",
}, {
"id": 39,
"name": "Label 3",
}, {
"id": 77,
"name": "Label 4"
}, {
"id": 100,
"name": "Label 5"
}]
}
},
"labels": [{
"id": 28,
"name": "Label 1",
"meta": {
"score": 3
}
}, {
"id": 17,
"name": "Label 2",
"meta": {
"score": 5
}
}]
};
}
]);
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="app" ng-controller="select">
<div ng-repeat="label in user.labels track by $index">
<div class="form-field">
<span>Label</span>
<select ng-model="user.labels[$index]" ng-options="department.name for department
in user.parent.grandparent.labels track by department.id">
</select>
</div>
<div>
<span>Score</span>
<select ng-model="label.meta.score">
<option value="1">1 (lowest)</option>
<option value="2">2</option>
<option value="3">3</option>
<option value="4">4</option>
<option value="5">5 (highest)</option>
</select>
</div>
</div>
<button ng-click="user.labels.push({})">Add Label</button>
</div>
You can use a filter function inside the ng-repeat to achieve this, here is a sample Codepen showing you how:
http://codepen.io/anon/pen/ZYveOo
You need to pass the filter in the repeat definition:
<select ng-model="user.labels[$index]" ng-options="department.name for department in user.parent.grandparent.labels | filter:removeSelected track by department.id ">
Which refers to this function on scope:
$scope.removeSelected = function(val){
return !_.find($scope.user.labels, function(label) {
return label.id === val.id;
});
};
Even then though I think you are missing one use case which is that you want to be able to have the currently selected label included in the options, by removing all selected options you are removing that ability.
Updated:
Ok then, so after giving this some thought I have come up with the following filter which could be optimised but does seem to work as expected:
.filter('duplicatesFilter', function() {
return function(items, index, selected) {
var res = [selected[index]];
_.forEach(items, function(item){
if(!_.find(selected, function(label) {
return label.id === item.id;
})){
res.push(item);
}
});
return res;
};
})
Use it like so:
<select ng-model="user.labels[$index]" ng-options="department.name for department in user.parent.grandparent.labels | duplicatesFilter:$index:user.labels track by department.id "></select>
This is something I have hit a few times and each time I've worked around it. I'll take a look later if I can find a custom filter that better solves the problem and if I can't I'll tidy up this code and release one; however this should be good to go for your use-case.
Working code-pen:
http://codepen.io/anon/pen/ZYveOo
I have this array in $scope.types (example data) :
[
{
"id": 1,
"description": "Cat",
"property_type": [
{
"id": 1,
"description": "Nickname",
},
{
"id": 2,
"description": "Age",
},
{
"id": 3,
"description": "Color",
}
]
}
]
I want to populate a ng-repeat with the properties of the type. Here's what I did :
<div ng-repeat="property in types[parseInt($('#select_type').val())].property_type">
{{property.description}}
</div>
This code doesn't show anything. However, if I replace $('#select_type').val() with 0, which is the offset of the object in the array, it works. What I don't understand is that if I look in the console what's the value of $('#select_type').val(), I get "0"... so it should work, unless there's something I don't get right with Angular (which is probably the case here).
If it can help, here's my select :
<select ng-options="type.id as type.description for type in types" ng-model="current_data.object_type_id" id="select_type">
<!-- Generated by ng-options, not hardcoded -->
<option value="0" selected="selected">Cat</option>
<option value="1">Dog</option>
</select>
Have any idea?
Try to use the following code:
<div ng-repeat="property in current_data.property_type">
{{property.description}}
</div>
<select ng-options="type.description for type in types" ng-model="current_data" id="select_type">
<option value="">select</option>
</select>
Try this on your ng-repeat
<div ng-repeat="property in types[current_data.object_type_id].property_type">
{{property_type.description}}
</div>