Line Chart not updating everytime - reactjs

So I am using Line from react-chartjs-2 and I've added an onClick event to the labels which blur all the lines except the current one.
Here is my onClick function code:
legend:{
'onClick': function(e, legendItem) {
var index = legendItem.datasetIndex;
var ci = this.chart;
console.log(ci.data.datasets);
//var alreadyHidden = (ci.data.datasets[index].borderColor === ci.data.datasets[index].accentFadedColor) ? false : true;
for(var i=0; i< ci.data.datasets.length;i++){
if (i !== index) {
ci.data.datasets[i].borderColor = ci.data.datasets[i].accentFadedColor;
} else if (i == index){
ci.data.datasets[i].borderColor = ci.data.datasets[i].accentColor;
}
}
that.updateValue(index);
ci.update();
}
The problem is, the function updates the chart on first click but not after that. Though I can see the updates values with console.log()
Any idea what I am doing wrong?
Update:
So apparently my chart is working fine. Inside the onClick() I'm making call to another function ( which sets state ) which is causing this behavior.
Here's a link to stackblitz
Any advice?

So apparently, just making the function call inside onClick() but before updating the datasets solved the problem.
I think rendering after setState and canvas update were somehow mixing up.
Here's the updated code:
legend:{
'onClick': function(e, legendItem) {
var index = legendItem.datasetIndex;
var ci = this.chart;
that.updateValue(index);
for(var i=0; i< ci.data.datasets.length;i++){
if (i !== index) {
ci.data.datasets[i].borderColor = ci.data.datasets[i].accentFadedColor;
ci.data.datasets[i].lineWidth = ci.data.datasets[i].highlightedWidth;
} else if (i == index){
ci.data.datasets[i].borderColor = ci.data.datasets[i].accentColor;
ci.data.datasets[i].lineWidth = ci.data.datasets[i].fadedWidth;
}
}
ci.update(); }

Related

Fabric.js group/ungroup - individual objects disappear while ungrouping

I have this functions in my angularJS controller:
function group(){
var activegroup = canvas.getActiveGroup();
var objectsInGroup = activegroup.getObjects();
activegroup.clone(function(newgroup) {
canvas.discardActiveGroup();
objectsInGroup.forEach(function(object) {
canvas.remove(object);
});
canvas.add(newgroup);
});
}
function ungroup(){
var activeObject = canvas.getActiveObject();
if(activeObject.type=="group"){
var items = activeObject._objects;
activeObject._restoreObjectsState();
canvas.remove(activeObject);
for(var i = 0; i < items.length; i++) {
canvas.add(items[i]);
canvas.item(canvas.size()-1).hasControls = true;
}
}
canvas.renderAll();
}
Working almost perfectly - jus when I ungroup the objects are not rendered (they are still in the canvas, but not visible). I can select the objects individually even if they are invisible. Selectin multiple object will show them while they are selected – deselecting one will let the other disappear. In short: ungrouping objects will not show as individual objects again.
This applys only to primitives like, box, circle, triangle. Text an images are not affected.
Help is appreciated!
function ungroup(){
var activeObject = canvas.getActiveObject();
if(activeObject.type=="group"){
var items = activeObject._objects;
alert(items);
activeObject._restoreObjectsState();
canvas.remove(activeObject);
for(var i = 0; i < items.length; i++) {
canvas.add(items[i]);
items[i].dirty = true; //set object dirty true
canvas.item(canvas.size()-1).hasControls = true;
}
canvas.renderAll();
}
}
If you set object dirty true, it will render in renderAll() call and redraw again.

UI Grid showing only last record many times on infinite scroll

Before Scrolling
After Scrolling
In Grid on first time load I am getting data properly.
After scrolling down it is getting problem.
It displays last record from the first load's last record in every row.
Below is my code for infinite scroll function.
$scope.getDataDown = function() {
var promise = $q.defer();
$scope.lastPage++;
if ($scope.data.length < $scope.total) {
$http(getRequest()).success(function(data) {
promise.resolve();
var jb = JSON.stringify(data.content);
$scope.gridApi.infiniteScroll.saveScrollPercentage();
$scope.data = $scope.data.concat(data.content);
$scope.total = data.total ? data.total : data.length;
$scope.length = $scope.data.length;
$scope.gridApi.infiniteScroll.dataLoaded(false,
$scope.lastPage < ($scope.total / $scope.pageSize));
}).error(function(error) {
$scope.gridApi.infiniteScroll.dataLoaded();
});
}
return promise.promise;
};
I figured it out. Funciton is right but I used below function in my code it was conflicting with this function
$scope.gridOptions.rowIdentity = function(row) {
return row.id;
};

Angular values update in both elements

I am adding same element (json object) into a list (from another list) twice using .copy to break the reference. But even after doing that when I change some values in one both of them are getting updated.
$scope.addProduct = function (item) {
var index = $scope.itemsProduct.indexOf(item);
$scope.scopItem = {};
angular.copy(item , $scope.scopItem);
for(var j in $scope.scopItem['ABC']) {
$scope.scopItem['ABC'][j].dataType='Discount';
$scope.scopItem['ABC'][j]['Discount'] = '';
}
if (index != -1) {
$scope.itemsTags.push($scope.scopItem);
$timeout(function() {
$scope.$apply(function () {
$scope.calculate($scope.scopItem);
});
}, 10);
}
};
$scope.calculateParam = function (indexQ) {
var index = $scope.itemsTags.indexOf(indexQ);
$scope.itemsTags[index]['ABC']['Discount'] = '10'; //or some other logic
}
Need help as even i am not adding the same element(using .copy) and updating the "Discount" property of one updates both??
Note: ABC is a inner list with property as "Discount" and I am changing "Discount"
Some comments:
for(var j in $scope.scopItem['ABC'])
it's absolutely incorrect and should be rewrited to
for(var j=0; j < $scope.scopItem['ABC'].length; j++)
also scopItem is changed in calculate method and stored in itemsTags

Angular NgStyle background image isn't refreshing

I am trying to change the background image based on window resize. I am getting the correct output in console in terms of the image path that I need. But for some reason the url just doesn't update in the div.
This is in a directive:
angular.element($window).on('resize', function(){
waitForFinalEvent(function(){
checkSize();
}, 500);
});
$scope.index = 0;
var checkSize = function(){
var width = angular.element($window).width();
var height = angular.element($window).height()
console.log('w: ' +width);
console.log('h: '+height);
$scope.index ++;
if(width < 1050 && width > 800 ) {
$scope.slideImage = $scope.displaySlideImageM;
console.log('here1: ' +$scope.slideImage);
} else if(width < 799 && height < 800) {
$scope.slideImage = $scope.displaySlideImageM;
console.log('here2: ' +$scope.slideImage);
} else if(width < 799 && height > 800) {
$scope.slideImage = $scope.displaySlideImageP;
console.log('here3: ' +$scope.slideImage);
} else {
$scope.slideImage = $scope.displaySlideImageO;
console.log('here4: ' +$scope.slideImage);
}
}
var waitForFinalEvent = (function () {
var timers = {};
return function (callback, ms) {
if (timers) {
clearTimeout(timers);
}
timers = setTimeout(callback, ms);
};
})();
html:
<div class="result-slide" ng-style="{'background-image':'url('+ slideImage +'?v='+ index +')'}"></div>
As you can see I tried adding a random param to the end of the url with ?v=n to attempt to trigger the refresh. But although the index changes, the physical slideImage url isn't updating.
Can someone please shed some light to this issue?
A quick scan of your code shows that you should be using $timeout, instead of setTimeout. While both things execute the timer fine, setTimeout occurs outside of angular so the $scope assignments will not be updated. If you do use setTimeout, then you need to wrap your assignment code in $scope.apply().
You can read about it more here. https://docs.angularjs.org/api/ng/service/$timeout

Ionic framework infinite scroll just have called one time

I have tried to build mobile app with ionic framework in the recent day. And I found that the list directy of ionic is very slow when it has just about 30 items or more, it's very bad. I've tried the bindonce method in angularjs to reduce the number of watchers but it's not help much. So I tried to use the infinite scroll function that ionic has.
My template is like this:
<view title="'Pet Information'">
<content has-header="true" has-tabs="true" on-infinite-scroll="loadMore">
<list>
<item ng-repeat="pet in pets" type="item-text-wrap" href="#/tab/pet/{{pet.id}}">
<h3>{{pet.title}}</h3>
<p>{{pet.description}}</p>
</item>
</item>
</list>
</content>
</view>
And my controller
.controller('PetIndexCtrl', function($scope, PetService) {
$scope.pets_all = PetService.all();
$scope.pets = [];
// Add just 10 pets at the first time
var count = 0;
for (var i = 0; i < 10; i++) {
$scope.pets.push($scope.pets_all[i]);
count++;
};
$scope.loadMore = function() {
var curr_count = count;
for (var i = curr_count; i < curr_count + 10; i++) {
if (i < $scope.pets_all.length) {
$scope.pets.push($scope.pets_all[i]);
count++;
} else {
return;
}
}
}
})
My idea is that the list will just load 10 items at the first time, and everytime user scroll to bottom edge of the phone it will call the loadMore function that will load 10 more items. But it seem that the loadMore function just have called one time, so that all I have is just the list of 20 items while my array is more than 100 items.
Maybe I'm wrong or the infinite scroll of ionic framework have error?
Seems there is a new way to do this in Ionic 2. Now you have to broadcast an event in the loadMore callback, to signalize that loading is finished.
$scope.$broadcast('scroll.infiniteScrollComplete');
I found what wrong with my code. I just missed the done callback in the code. I saw it in the example on github but I've just thought that it's a option not require, poor me :)
$scope.loadMore = function(done) {
$timeout(function(){
var curr_count = count;
for (var i = curr_count; i < curr_count + 7; i++) {
if (i < $scope.pets_all.length) {
$scope.pets.push($scope.pets_all[i]);
count++;
} else {
return;
}
}
done();
}, 1000);
}
For angular2/typescript ionic firebase app, the code below worked.
Set $event.state = "closed"; to call the function more than one time. The complete code is given below for reference.
In the component,
Import
import { AngularFireDatabase, FirebaseListObservable } from 'angularfire2/database';
Declare
limit: number = 10;
itemRef:FirebaseListObservable<any[]>;
itemList:any;
loadeditemList:any;
Firebase Call
getData(){
this.itemRef = this.firebase.list('quote', {
query: {
orderByChild: 'title',
limitToFirst:this.limit
}
});
}
Scroll Call
onInfiniteScroll($event:any) {
this.limit += 10;
this.getData();
this.itemRef.forEach((itemList:any) => {
let items:any = [];
itemList.forEach( (item:any) => {
items.push(item);
return false;
});
this.itemList = items;
this.loadeditemList = items;
$event.state = "closed";
});
}
HTML
<ion-list>
...
</ion-list>
<ion-infinite-scroll (ionInfinite)="onInfiniteScroll($event)">
<ion-infinite-scroll-content></ion-infinite-scroll-content>
</ion-infinite-scroll>
Call getData() and inject firebase in constructor.
private firebase: AngularFireDatabase

Resources