How to drill down MAKit Chart with clicked category? - javascript

In a SAPUI5 application I am using two XML views showing a Chart each with a model bound to an OData service.
On the first view I build the chart using the following code:
<ma:Chart id="idChart" height="90%" width="100%" type="Column"
rows="{/MySet}" tap="onTapEvt">
<ma:category>
<ma:Category column="category" displayName="Category" />
</ma:category>
<ma:series>
<ma:Series column="intervallSeries" displayName="Intervall"/>
</ma:series>
<ma:values>
<ma:Value expression="mValue" displayName="Anzahl" />
</ma:values>
<ma:columns>
<ma:Column name="category" value="{Category}" />
<ma:Column name="intervallSeries" value="{Intervall}" />
<ma:Column name="mValue" value="{Anzahl}" type="number" />
</ma:columns>
</ma:Chart>
Let's assume I have four categories in my example chart named 'A', 'B', 'C' and 'D'.
When I click on the category 'C' in the Chart I would like to show another Chart on the next page using the filtered data from my OData service by filtering on "Category eq 'C'".
Therefore I use the function
onTapEvt: function(oEvent) {
var selectedCategory = oEvent.oSource._selectedCatIdx; // 2 when I select 'C'
// --> How do I get Category value 'C' instead of selectedIndex 2 here <--
app.to("nextPage", "slide", selectedCategory);
}
The object oEvent.oSource has all the MAKit Chart data in it, e.g. the selected index of the category in which I have clicked.
Now I am searching for a way to read the bound value of Category with index 2 from the chart.
Any ideas? In the SAPUI5 SDK I could not find a useful method for this.

You can use the following code to get the selected category :
var myChart = this.getView().byId("idChart");
var cat = myChart.getSelectedCategory();

Related

angularjs add new model property for view

I am new at angularjs and getting data from api like this:
function response(data){
$scope.data = data
}
<<<< data format is ilke this >>>>>
[
{"id":"1", "name":"item1"},
{"id":"2", "name":"item2"},
{"id":"3", "name":"item3"}
];
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<>
Using this in view page with ng-repeat:
<button ng-repeat="item in data">{{item.name}}</button>
I will change selected item button color. But I need selected property on items. But it does not comes from database.
How can I add property named selected to items? in view or in controller?
I think you can use ng-init in repeat as,
<button ng-repeat="item in data" ng-init="item.selected = false">{{item.name}}</button>
this will add a selected property for each and every repeating object with the value of false.
Did you try a simple loop ?
$.each($scope.data, function( index, item ) {
item.selected = false;
});
You can initialize the selected attribute for all data items:
for (var i in data){
data[i].selected = false;
}
and then change it on click:
<button ng-repeat="item in data" ng-click="item.selected=true">{{item.name}}</button>

Filter variable not updating in controller angularjs

Hi Im attempting to build functionality around the length of a filter in angularjs, and although its working as it should in the view, in the controller the variable seems to stay outdated...
When I click on the div below it filters a list and calls the filterby function. The output of the length of the newly filtered list updates in the view correctly. However in the function itself I have a log set and it is still showing the old length when I click on the div.
<div ng-repeat="filter in filters" ng-click="filterby(filter.filter_type)">{{filter.filter_type}}</div>
<ul>
<li ng-repeat="event in filtered = (events | filter:query) | orderBy:'-event_date' ">
<span >{{event.event_date}},{{event.event_name}}, {{event.event_venue}}, {{event.event_description}} </span>
</li>
</ul>
<br />Length of filtered items {{filtered.length}}
And my view....
$scope.filterby = function(filterby) {
if (filterby == 'ALL') {
$scope.query = '';
}
else {
$scope.query = filterby;
}
console.log($scope.filtered.length);
};
My filter data:
$scope.filters = [
{'filter_type' : 'ALL'},
{'filter_type' : 'Macnass'}
];
EDIT: Ok its not that it nots working at all, its just showing the previous value, as if its one click behind all the time, so its something to do with the fact that the variable in the view is updated after the list is made. but Im not sure how to go about insuring the variable in the controller is the latest value.
Plunker: http://plnkr.co/edit/u7KpqYx8gDwaaXEvGeMn?p=preview
check out the plunker
added below
$scope.filtered = $filter('filter')($scope.events, $scope.query)
in $scope.filterby function

AngularUI-Bootstrap Typeahead: Grouping results

I am implementing typeahead using AngularUI-Bootstrap. I need to show the results grouped based on some values coming from the database. Here's a sample scenario
There are some users in the database, each user has a "Department". One user name can be available in multiple departments.
The end-user types in the names to search users from the database and retrieves the list in the typeahead list. Since one user name can belong to multiple departments, the requirement is to show the user names grouped by different departments. Something like this:
Then the user can select the desired user name and proceed.
As per the Typeahead documentation present here, I don't see any option to cater to my requirement.
I have tried the this workaround: Whenever the typeahead array is getting formed, I appended the user department to the array element:
$scope.fetchUsers = function(val) {
console.log("Entered fetchUsers function");
return $http.get("http://localhost:8080/TestWeb/users", {
params : {
username : val
}
}).then(function(res) {
console.log("Response:",res);
var users = [];
angular.forEach(res.data, function(item) {
users.push(item.UserName + " - " + item.UserDepartment);
});
console.log("users=",users);
return users;
});
};
This way, at least the end user sees the department. But when I select the record, the selected value is the full content of the array element. Below is sample screenshot to elaborate:
HTML
Users from local service
<pre>Model: {{userList | json}}</pre>
<input type="text" ng-model="userList" placeholder="Users loaded from local database"
typeahead="username for username in fetchUsers($viewValue)"
typeahead-loading="loadingUsers" class="form-control">
<i ng-show="loadingUsers" class="glyphicon glyphicon-refresh"></i>
User types in the string
User selects one record
I want to avoid the department (in this case, string - Desc 4 ) when user selects a record.
Is there any way I can achieve this grouping without any workaround? Or is there any way I can enhance my workaround?
I used to have a similar requirement and here is how I did it that time.
Example Plunker: http://plnkr.co/edit/zujdouvB4bz7tFX8HaNu?p=preview
The trick is to set the typeahead-template-url to a custom item template:
<input type="text" class="form-control" placeholder="Users loaded from local database"
ng-model="selectedUser"
typeahead="user as user.name for user in getUsers($viewValue)"
typeahead-template-url="typeahead-item.html" />
The item template, this represent each item in a dropdown:
<div class="typeahead-group-header" ng-if="match.model.firstInGroup">Desc {{match.model.group}}</div>
<a>
<span ng-bind-html="match.label | typeaheadHighlight:query"></span>
</a>
As you can see, there is an ng-if to show a group header if that item has a property firstInGroup set to true.
The firstInGroup properties are populated like this using lodashjs:
$scope.getUsers = function (search) {
var filtered = filterFilter(users, search);
var results = _(filtered)
.groupBy('group')
.map(function (g) {
g[0].firstInGroup = true; // the first item in each group
return g;
})
.flatten()
.value();
return results;
}
Hope this fit to your requirement too.
please see here http://plnkr.co/edit/DmoEWzAUHGEXuHILLPBp?p=preview
instead of creating new objects here:
angular.forEach(res.data, function(item) {
users.push(item.UserName + " - " + item.UserDepartment);
});
use create template :
<script type="text/ng-template" id="customTemplate.html">
<a> {{ match.model.name}} - department : {{match.model.dept}}</a>
</script>
and use it in your Typeahead directive
<input type="text" ng-model="selected"
typeahead="user.name as user for user in users | filter:$viewValue | limitTo:8" class="form-control"
typeahead-template-url="customTemplate.html">

delete row(s) from ng-grid table from button

I have a table with ng-grid, and the problem is that i'm not sure how to collect the selected row(s) id or variable to pass into my delete function.
here is a quick mockup of what i'm trying to do
http://plnkr.co/edit/zy653RrqHmBiRJ7xDHlV?p=preview
the following code is from my html, a clickable delete button that takes in 2 parameters, the array of checkbox ids and the index at the corresponding table. This delete method was obtained from this tutorial : http://alexpotrykus.com/blog/2013/12/07/angularjs-with-rails-4-part-1/
<div class="btn-group">
<button class="my-btn btn-default button-row-provider-medical-services" ng-click="deleteProviderMedicalService([], $index)">Delete</button>
</button>
</div>
<div class="gridStyle ngGridTable" ng-grid="gridOptions">
</div>
The following code grabs the json data from a url, queries it and returns it. It also contains the delete function that gets called from the controller in the html page.
app.factory('ProviderMedicalService', ['$resource', function($resource) {
function ProviderMedicalService() {
this.service = $resource('/api/provider_medical_services/:providerMedicalServiceId', {providerMedicalServiceId: '#id'});
};
ProviderMedicalService.prototype.all = function() {
return this.service.query();
};
ProviderMedicalService.prototype.delete = function(providerId) {
this.service.remove({providerMedicalServiceId: providerId});
};
return new ProviderMedicalService;
}]);
The following is my controller(not everything, just the most important bits). $scope.provider_medical_services gets the json data and puts it into the ng-grid gridOptions.
After reading the ng-grid docs, i must somehow pass the checkbox ids from the selectedItems array and pass it into html doc to the delete function. Or, i'm just doing this completely wrong, as i hacked this together. Solutions and suggestions are greatly appreciated
(function() {
app.controller('ModalDemoCtrl', ['$scope', 'ProviderMedicalService', '$resource', '$modal', function($scope, ProviderMedicalService, $resource, $modal) {
var checkBoxCellTemplate = '<div class="ngSelectionCell"><input tabindex="-1" class="ngSelectionCheckbox" type="checkbox" ng-checked="row.selected" /></div>';
$scope.provider_medical_services = ProviderMedicalService.all();
$scope.deleteProviderMedicalService = function(ids,idx) {
$scope.provider_medical_services.splice(idx, 1);
return ProviderMedicalService.delete(ids);
};
$scope.gridOptions = {
columnDefs: [
{
cellTemplate: checkBoxCellTemplate,
showSelectionCheckbox: true
},{
field: 'name',
displayName: 'CPT Code/Description'
},{
field: 'cash_price',
displayName: 'Cash Price'
},{
field: 'average_price',
displayName: 'Average Price'
},
],
data: 'provider_medical_services',
selectedItems: []
};
i think the easiest option is pass an (array index) as data-id to your dom, which u can pick it from there.
{{$index}} is a variable you can use in ng-repeat
======= ignore what i said above, since i normaly writes my own custom stuff ======
I just had a look at ng-grid, i took their example. i've added a delete all selected function, as well as someone elses delete current row function ( these is pure angular way ) to see the code, hover over the top right corner < edit in jsbin >
http://jsbin.com/huyodove/1/
Honestsly i don't like it this way, you would be better off use something like lodash to manage your arrays and do your own custom grid. Using foreach to find the row index isn't good performance.
In their doc, it says you can change the row template, and which you should, so you can add the {{index}} to that row, and filter your data through that index rather which is a little bit better. anyway beware of deleting cells after you have filter your table.
I don't quite get much your question, but you can access to selectedItems of ng-grid as following: $scope.gridOptions.$gridScope.selectedItems (see ng-grid API for more information, but technically this array holds the list of selected items in multiple mode - or only one item in single mode)
For your case, the deleteAll() function could be someething like this:
$scope.deleteAll = function() {
$scope.myData = [];
}
The delete() function which delete selected items can be:
$scope.delete = function() {
$.each($scope.gridOptions.$gridScope.selectedItems, function(index, selectedItem) {
//remove the selected item from 'myData' - it is 2-ways binding to any modification to myData will be reflected in ng-grid table
//you could check by either name or unique id of item
});
}

angularJs - Is it possible for 2 different models of different structures to sync or share states?

I have a list of checkboxes and values I"m loading from a list which comes back from the database.
Controller
listA = ['item1','item2'...'itemn']; //Master list of items
$scope.selectedItems = ["item1",... "item5"]; //selected items
$scope.attributesModel = [ //new model based on selected items
{"index":5,"attribute":"item1"},
{"index":10, "attribute":"item2"},
{"index":13, "attribute":"item3"},
{"index":21, "attribute":"item4"},
{"index":24, "attribute":"item5"}
];
View part 1
<td>
<div class="checkbox checkbox-notext">
<input checklist-model="selectedItems" checklist-value="key" type="checkbox" id="{{key}}" ng-disabled="exceededLimit && !checked" />
</div>
</td>
<td>
<label for="{{key}}">{{key}}{{$index}}</label>
</td>
view part 2
<div ng-repeat="(index, row) in attributesModel" >
<div class="margin10">
<div>Index<input ng-model="row.index" value="row.index" type="number" class="indexInputs"></input>{{row.attribute}}</div>
</div>
</div>
Now I would like to sync $scope.selectedItems and $scope.attributesModel. When a checkbox is deselected, both selectedItems and attributesModel models remove that item, and vice versa. So every time someone checks a new checkbox they are presented a attributesModel with an empty text field to type the index value.
catch The index key is null initially for every newly selected item that is added to attributesModel. The user must enter a new index # once the new item is created.
I've tried using watch but the problem I run into is when a new item is selected, I don't have access to the item itself. I only have access to the list without any idea whether the new item is X or if the item removed is Y in order to push/delete the right item.
So this might be a watch solution that I'm missing.
Let me know if I can clarify anything.
I am not sure what the problem is, but you could use ngChange on the checkboxes:
<input type="checkbox" ... ng-change="..." />
I asdume you have a checklist directive or something, so should do something there, but (since you don't share it with us) I can't tell what exactly :)
UPDATE:
Since the checklist directive is an external dependency, you could handle the ng-chage in your code:
<input type="checkbox" ... ng-change="changed(key)" />
/* In the controller: */
...
$scope.changed = function (key) {
if ($scope.selectedItems.indexOf(key) === -1) {
// The checkbox for `key` was unchecked...
} else {
// The checkbox for `key` was checked...
}
};

Categories

Resources