ngOptions: add tooltip to selection - javascript

using the following json collection:
$scope.searchscope = [
{ id: 0, name: "Base", description: "Search only the specified base object. The value is equal to 0." },
{ id: 1, name: "OneLevel", description: "Search the child objects of the base object, but not the base object itself.The value is equal to 1" },
{ id: 2, name: "Subtree", description: "Search the base object and all child objects. The value is equal to 2" }
];
and the following markup
<select data-ng-model="mySelections[0].SearchFilterMembershipsScope" data-ng-options="i.id as i.name for i in searchscope" data-ng-required="true"></select>
I have successfully generated a select with the 3 options. What would be the best angular way to display a tooltip of the currently selected items "description"? Also would it be possible to do this whilst the user is navigating the dropdown, i.e. making a choice, verses actually had made the choice?

You would need a map from id → description. One way to populate it would be:
$scope.idToDescription = null;
$scope.$watch("searchscope", function(newval) {
if( newval != null ) {
$scope.idToDescription = {};
var i;
for( i=0; i < newval.length; i++ ) {
$scope.idToDescription[newval[i].id] = newval[i].description;
}
}
});
And in your template use it as:
<select ...
title="{{ idToDescription[mySelections[0].SearchFilterMembershipsScope] }}">

If you are using Twitter Bootstrap, you might also consider looking at Tooltips in
UI Bootstrap and if you want fancier select boxes consider using ui-select2 based on Select2.

Related

How to update the columnDef of an angular ui-grid column dynamically

So the issue I'm facing is I would like to update the field property of a columnDef definition to show a different value based on some configuration that's being passed into the directive. I have a dumbed down version in this plunk:
http://plnkr.co/edit/gmjUcQsnIOpqWwkoYiI8?p=preview
Clicking the button in that plunk should switch the emails from actual to pretend. It's looping over the columnDefs on scope and then altering the field to be email.pretend from email.actual. Do I need some kind of "refresh" function after changing the columnDefs? I tried gridApi.core.refresh() but that did not do anything. Thanks for any input!
http://plnkr.co/edit/ujIpJFFGRAwNUKiy0Bnm?p=preview
$scope.otherColumn = {displayName: 'Pretend', field: 'email.pretend'};
//change the field - is this possible???
$scope.changeField = function changeField() {
$scope.otherColumn = $scope.columnDefs.splice(1, 1, $scope.otherColumn)[0];
}
You just add / remove the item from the columnDefs array and it will do it.
So I thought I could update my grid similar to this but by reassigning an array to the columnsDef like this
var a = true;
//change the field - is this possible???
$scope.changeField = function changeField() {
if (a) {
$scope.columnDefs = [{ field: 'name' }, {
displayName: 'Pretend',
field: 'email.pretend'
}];
} else {
$scope.columnDefs = [{ field: 'name' }, {
displayName: 'Email',
field: 'email.actual'
}];
}
a = !a;
};
If you put that in the plnkr you'll see it doesn't have any effect.
That's because the assignment doesn't change the $scope.gridApi.
As #dave's answer suggests you need to modify the original columnsDef object from the initialization or the columns under the api won't be affected. I'm glad the code doesn't clone the object for the api or I'd have to dig into the api to make this change.

How to implement bi-directional connection between two arrays?

In my app I have an ItemsService which gets Items from Server and stores them as JSON objects in its cache variable. Items can be present in many places, e.g. in table or in graph/chart and so on.
For example, when I initialize a table - I need to pick only specific Items from cache, e.g. 1st, 3rd, 7th.
How to implement bi-directional connection between them? Basically I want table to contain references to specific items from cache so when I change an Item either in cache or in table - its state will be in sync all the time because it's the same Item.
Also when I delete Item from table - it needs to be removed from cache.
Here's example of table and cache structures:
Table:
table: {
"36": { // it's a name of a row
"72": [items], // it's a name of a column with corresponding items
"73": [items],
"74": [items]
},
"37": {
"72": [],
"73": [items],
"74": [items]
},
"38": {
"72": [],
"73": [],
"74": []
}
}
ItemsService cache (simplified version):
ItemsService = {
cache: [items]
};
Item structure:
{
id: 3,
parent_id: 1,
name: 'First Item',
siblings: [1,2,3],
active_users: [{user_id: 1, avatar_url: 'http://...'}, ...],
// 50 more fields :)
}
Also need to point out that I use angular-ui-sortable plugin to allow dragging of Items between columns/rows and I need to provide ng-model with array(I think). Here's how it looks right now:
<td ui-sortable="vm.sortableOptions"
ng-model="vm.table[row.id][column.id]">
<sb-item itemid={{item.id}}
ng-repeat="item in vm.table[row.id][column.id]">
</sb-item>
</td>
Unless for some reason you have to use two separate arrays, have you considered using a filter?
Your best bet would be objects. Variables that hold objects in javascript aren't really holding the object but a reference to said object. When you pass that variable into another one, the reference value gets copied so both variables point toward the same object.
var a = { 0: 'Property 0' };
var b = a;
b[0] = 'Property 0!'; //a[0] also the same.
delete b[0]; //a[0] nor b[0] exist anymore.
Using objects (rather than JSON) would work.
Then your cache and your table both point to same item objects. If you change something in the object, it is reflected at both ends.
var cacheArray = [{ item: 1 }, { item: 2}];
table[0][0] = cacheArray[0];
console.log(table[0][0].item); // 1
cacheArray[0].item = 9;
console.log(table[0][0].item); // 9.
Please note that the array and the table have not changed. They still point to the same objects.

The JSON parsed into HTML, how objects are mapped to corresponding HTML?

For example, the following JSON:
{
"A" : [{
name : "admin",
email:"xxx#msn.com"
},{
name : "anly",
email:"xxx#msn.com"
}]
"B" : [{
name : "beta",
email:"xxx#msn.com"
},{
name : "b",
email:"xxx#msn.com"
}]
}
Html formatted as follows:
<ul>
<li>admin</li>
<li>anly</li>
<li>besta</li>
<li>bestb</li>
</ul>
How By clicking li, found to their corresponding object?
I think the method is:
1, by traversing JSON find, but this way is time-consuming, not simple
2, which is bound to the data key and index attributes above and through the key index to find, but if some of the more complex data structures, as too cumbersome, and do not know that there is no other better way to achieve it?
The above content is translated through Google, I do not know whether a clear description of my problem?
Here are two examples of what I wrote myself realized:
http://jsfiddle.net/18q41mfr/
It all depends on your requirements. How large will this JSON object be and how frequently will it change?
For small or constantly changing JSON objects, it might be just fine to do the method 1.
For large and constant JSON objects, go with method 2. A cleaner way to achieve method 2 that you've suggested is to make use of the Underscore.js values and groupBy method.
Merge all values in your object with the var merged = _.values(object)
Group by name var formatted = _.groupBy(merged, 'name');
Resulting JSON is such:
{
admin: {
name : "admin",
email:"xxx#msn.com"
},
anly: {
name : "anly",
email:"xxx#msn.com"
},
...
}
Use the following code to get the value in your onclick event function on your li element:
formatted[this.innerHTML].email
It seems that you're already using jQuery; you can simply stuff the object references into your HTML elements using .data().
Internally, an object reference map is maintained and the HTML element stores the reference key in a special property name.
var items = {
"type_a" : [{
name : "test",
color : "red"
},{
name : "test",
color : "blue"
}],
"type_b" : [{
name : "test",
color : "orange"
},{
name : "test",
color : "yellow"
}]
};
for (var i in items) {
for (var j = 0; j < items[i].length; j++) {
$('<li>', {text: items[i][j].name})
.data(items[i][j])
.appendTo('#items');
}
}
$("#items").on("click", "li", function() {
var obj = $(this).data();
$("#detaila").html('name:' + obj.name + '<br>color:' + obj.color + '<br>' );
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<ul id="items"></ul>
<div id="detaila"></div>
<div id="detailb"></div>
Your second method is kind of good enough.
Maintain a global object myObjs for searching, whose keys are name and the values are object itself.
For each of the objects like:
var obj = {
name : "beta",
email:"xxx#msn.com"
}
myObjs[obj[name]] = obj; // If the name is not unique, add an id.
Then bind the key to the HTML element:
<li data-key="admin">admin</li>
When the element is clicked, find the key, query myObjs and find the obj. Something like (assume you are using jQuery):
$('ul').on('click', 'li', function() {
var $this = $(this);
var name = $this.data('key');
var obj = myObjs[name];
console.log(obj); // Here is your corresponding object.
});
Cons: extra memory
Pros: fast.

Jquery: Autocomplete with label

I am trying to learn website development.
While learning autocomplete feature of jquery, I tried to put in the labels.
function autocomplete (data) {
var data = data.toString();
var availableTags = data.split(',');
var autocompleteData = [];
for (var i = 0; i < availableTags.length; i++){
autocompleteData[i] = {};
autocompleteData[i].label = i.toString();
autocompleteData[i].value = availableTags[i];
}
$("#tags").autocomplete({
source: autocompleteData,
select: function (event, ui) {
printautocomplete(event, ui)
}
});
};
The autocomplete[i].value is a valid string.
autocompleteData[0]
Object {label: 0, value: "Peter"}
However, I do not see any suggestions.
What is wrong with the way I am using the API?
The API says:
"Array: An array can be used for local data. There are two supported formats:
An array of strings: [ "Choice1", "Choice2" ]
OR An array of objects with label and value properties: [ { label: "Choice1", value: "value1" }, ... ]
The label property is displayed in the suggestion menu. The value will be inserted into the input element when a user selects an item. If just one property is specified, it will be used for both, e.g., if you provide only value properties, the value will also be used as the label. "
Thank you.
$('#sidebarSearch').autocomplete(
{
source: function(query, result)
{
var query = $('#sidebarSearch').val ();
$.ajax(
{
url:"sidebarSearchFetch.php",
method:"POST",
data:{query:query},
dataType:"json",
success:function(data)
{
result($.map(data, function(item)
{
return {
label: item.name,
value: item.usrId
};
}));
}
})
},
appendTo: "#sidebar-form"
});
I am skeptical of line 2 in your code (var data = String()data;) I would use: var data = data.toString();
But if you are sure that the autocompleteData elements do indeed have valid strings, then my best guess would be that perhaps you forgot to give the '#tags' id to your html entry field element.
Finally, if this is not it, to troubleshoot, I would try removing the select: option from the object you are passing to autocomplete() in the line that begins: $("#tags").autocomplete(... so that only the source options is passed.
Another thing to check out is when the code is being run. It is possible that a document.ready() function is needed to ensure that that when the autocomplete feature is added to the DOM element with the id '#tags', that the element has already been created.
The autocomplete works fine. Instead of completing "value", it completes "label".
So when I type in "1", it suggests "1", "10", "11", etc.
Autocomplete applying value not label to textbox answers how to change to to by-value.

How to filter dynamic inputs using grep() function of jQuery

I'm using "grep" function of jQuery to filter the data,the below code sample works fine as the condition is static.
But if "name" and "school" parameter has more than one value how to filter it..?, Consider i receive name & school from multiple checkbox list.Ideally i do not want to hard code
var students =
[ {'id':1, 'name':'amit', 'school':'st john'},
{'id':2, 'name':'ankit','school':'st mary'},
{'id':3, 'name':'john', 'school':'hill school'},
{'id':4, 'name':'matt', 'school':'st john'}];
jQuery.grep(students,function(student)
{ return student.name =='john' && student.school=='st.john' });
//something like this is possible?
{ student.name =='john||jack||stella' && student.school=='st.john||st.mary' });
You can do it but not quite the way you're thinking:
var names = [ 'john', 'jack', 'stella' ];
var schools = [ 'st john', 'st mary' ];
var matches = jQuery.grep(students, function(student) {
return names.indexOf(student.name) != -1
&& schools.indexOf(student.school) != -1;
});
So you just need to set up your names and schools arrays based on your dynamic inputs and away you go.

Categories

Resources