Why chartjs is not drawing in interior of a div? - html

I have a problem with ChartJs, because I try to put in interior of a div with class="col-6", it's only working if that class="row" and don't understand why.
pie-chart.components.ts:
ngOnInit() {
this.labels = ["ONE", "TWO", "THREE"];
this.chartInit();
}
chartInit() {
let chartElement = this.elementRef.nativeElement.querySelector("#myChart");
chartElement.width = 750;
chartElement.height = 750;
this.pieChart = new Chart(chartElement, {
type: "outlabeledPie",
data: {
labels: this.labels,
datasets: [
{
backgroundColor: [
"#FF3784",
"#36A2EB",
"#4BC0C0",
"#F77825",
"#9966FF",
"#00A8C6",
"#379F7A",
"#CC2738",
"#8B628A",
"#8FBE00"
],
data: [1, 2, 3]
}
]
},
options: {
plugins: {
legend: false,
outlabels: {
text: "%l %p",
color: "white",
stretch: 20,
font: {
resizable: true,
minSize: 12,
maxSize: 25
}
}
},
responsive: true
}
});
}
pie-chart.components.html:
<canvas id="myChart" height="750" width="750"></canvas>
home.components.html:
<div class="row">
<div class="col-6 text-center">
Available books
<app-pie-chart></app-pie-chart>
</div>
<div class="col-6 text-center">
Lended books
<app-pie-chart></app-pie-chart>
</div>
</div>
The code that is working (but I don't want this version):
<div class="row">
<div class="row text-center">
Available books
<app-pie-chart></app-pie-chart>
</div>
<div class="row text-center">
Lended books
<app-pie-chart></app-pie-chart>
</div>
</div>
So how can I display that two pie charts in interior of that two divs? And the second question is: why is only working in a div with class="row", and in a div without class or with other class it doesn't display anything?
Thank you!

Related

Bootstrap - Margins causing columns to wrap to next line when using canvas

I am trying to place two charts next to each other with some padding or margins between the columns. I have no issues if the columns contain text but not working with the canvas tag. If I place them side-by-side with no margin it works okay, but adding a margin causes the chart to wrap to the next line.
I've tried adding gutters, padding, container vs container-fluid. Adding mx-# will sometimes work but snap to the next line on resize.
var data = {
labels: ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul"],
datasets: [{
label: "Dataset #1",
backgroundColor: "rgba(255,99,132,0.2)",
borderColor: "rgba(255,99,132,1)",
borderWidth: 2,
hoverBackgroundColor: "rgba(255,99,132,0.4)",
hoverBorderColor: "rgba(255,99,132,1)",
data: [65, 59, 20, 81, 56, 55, 40],
}]
};
var options = {
maintainAspectRatio: true,
scales: {
y: {
stacked: true,
grid: {
display: true,
color: "rgba(255,99,132,0.2)"
}
},
x: {
grid: {
display: false
}
}
}
};
new Chart('bar-chart', {
type: 'bar',
options: options,
data: data
});
new Chart('bar-chart2', {
type: 'bar',
options: options,
data: data
});
<link href="https://cdnjs.cloudflare.com/ajax/libs/bootstrap/5.0.2/css/bootstrap.min.css" rel="stylesheet"/>
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/3.5.1/chart.min.js"></script>
<div class="container-fluid">
<div class="row p-2 bg-dark ">
<div class="col-6 bg-white shadow rounded">
<h3>Col1</h3>
<canvas id="bar-chart"></canvas>
</div>
<div class="col-6 bg-white shadow rounded">
<h3>Col2</h3>
<canvas id="bar-chart2"></canvas>
</div>
</div>
</div>
Since you're using two col-6, they take up the whole space (12 cols) so adding a margin forces the second to go the next line, i suggest putting your content inside another div inside col-6 with some padding:
.mycanvas {
padding: 10px;
}
<div class="col-6">
<div class="mycanvas bg-white shadow rounded">
<h3>Col1</h3>
<canvas id="bar-chart"></canvas>
</div>
</div>
<div class="col-6">
<div class="mycanvas bg-white shadow rounded">
<h3>Col2</h3>
<canvas id="bar-chart2"></canvas>
</div>
</div>

AngularJS nested objects in the same bootstrap row

i have a JSON object
{
"products": [
{
"devices": [
{
"label": "P1D1"
},
{
"label": "P1D2"
}
]
},
{
"devices": [
{
"label": "P2D1"
},
{
"label": "P2D2"
}
]
}
]
}
and i want to have in HTML something like this
<div class="row">
<div class="col-3">
P1D1
</div>
<div class="col-3">
P1D2
</div>
<div class="col-3">
P2D1
</div>
<div class="col-3">
P2D2
</div>
</div>
AngularJS is the language i am using, but i don't seem the find the right syntax
<div class="row">
<div ng-repeat="product in obj.products">
<div class="col-3" ng-repeat="device in product.devices">
{{device.label}}
</div>
</div>
</div>
How can i achieve all the subitems to be displayed in a bootstrap column next to eachother?
I think you can't do it directly using only HTML. Alternatively you can use some manipulation in Javascript to flatten your data.
JAVASCRIPT
$scope.getItems = function(){
return $scope.obj.products.flatMap(function(element){
return element.devices;
})
}
HTML
<div class="col-3" ng-repeat="device in getItems()">
{{device.label}}
</div>
Check my example:
https://codepen.io/avgustint/pen/XWYyoyd?editors=1111

Nested Children Json in Angular HTML

I have a JSON with nested children. RowElements can have n colElements and colElements can have n RowElements.
JSON
"container": {
"id": "37ec0632-3391-4ef5-a9cb-25db2216fa75",
"rowElements": [
{
"id": "80e1dae7-b497-48d3-80ad-b94d36ada642",
"colElements": [
{
"id": "c662efe9-615c-4de5-97d3-2b02a5bce831",
"rowElements": [
{
"id": "b31960fd-c082-4d3b-88fc-c05f0cf837aa",
"colElements": []
},
{
"id": "7552306a-ca61-4d80-bb4e-d6c8d15c2c78",
"colElements": []
},
{
"id": "f669896d-132b-468e-8dcf-f2b59d509a76",
"colElements": []
}
]
}
]
}
]
}
How can i iterate over the children dynamically in the template like:
<div class="row">
<div class="col">
<div class="row">
<div class="col">
</div>
<div class="col">
</div>
<div class="col">
</div>
...
</div>
...
</div>
...
</div>
You can use nested *ngFor to iterate the JSON and display it dynamically.
I also created a stackblitz for you to check my solution.
HTML - I'm display the id here just to check the JSON.
<div class="row" *ngFor="let firstRow of arr.container.rowElements">
{{ firstRow.id }}
<div class="col" *ngFor="let firstCol of firstRow.colElements">
{{ firstCol.id }}
<div class="row" *ngFor="let secondRow of firstCol.rowElements">
{{ secondRow.id }}
<div class="col" *ngFor="let secondCol of secondRow.colElements"></div>
</div>
</div>
</div>
AppComponent.ts - I added a variable to hold your sample JSON
export class AppComponent {
arr = {
container: {
id: '37ec0632-3391-4ef5-a9cb-25db2216fa75',
rowElements: [{
id: '80e1dae7-b497-48d3-80ad-b94d36ada642',
colElements: [{
id: 'c662efe9-615c-4de5-97d3-2b02a5bce831',
rowElements: [{
id: 'b31960fd-c082-4d3b-88fc-c05f0cf837aa',
colElements: []
},
{
id: '7552306a-ca61-4d80-bb4e-d6c8d15c2c78',
colElements: []
},
{
id: 'f669896d-132b-468e-8dcf-f2b59d509a76',
colElements: []
},
],
}, ],
}, ],
},
};
constructor() {
console.log(this.arr.container);
}
}

Swiper.js not able to render the 'Apex-Chart'-Series when swipe between (first to last) or (last to first) slide

I'm facing an unknown issue only when I'm swiping between last (swiper-slide) to first (swiper-slide) and same as first to last, but when I do just a half swipe, then the RedialBar looks good.
I set the loop: true. I have 3 Slides. Inside all Slide, i have a very simple APEX RadialBar/Circle Chart's. Everything works nice. But when I slide 1 to 2 Good. 2 to 3 Good. But when I slide 3 to 1 then the RadialBar series does not render. And same problem when I slide 1 to 3. So if I just do a half slide (just a little swipe), then the RadialBar render perfectly.
$(document).ready(function () {
//initialize swiper when document ready
var mySwiper = new Swiper ('.swiper-container', {
// Optional parameters
direction: 'horizontal',
loop: true,
pagination: {
el: '.swiper-pagination',
type: 'bullets',
clickable: true
},
effect: 'slide'
})
mySwiper.on('slideChange', function () {
console.log('slide changed');
});
});
// Apex Chart
let options = {
series: [50],
chart: {
height: 200,
type: 'radialBar',
},
plotOptions: {
radialBar: {
hollow: {
size: '70%',
}
},
},
stroke: {
lineCap: 'round'
},
labels: ['Country'],
};
let chart = new ApexCharts(
document.querySelector("#demo-chart-1"),options
);
let chart2 = new ApexCharts(
document.querySelector("#demo-chart-2"),options
);
let chart3 = new ApexCharts(
document.querySelector("#demo-chart-3"),options
);
chart.render();
chart2.render();
chart3.render();
body {
background-color: #a3d5d3;
}
.india,
.canada,
.japan {
height: 100;
border: 1px solid green;
display: grid;
place-items: center;
}
<script src="https://unpkg.com/swiper/js/swiper.min.js"></script>
<script src="https://code.jquery.com/jquery-3.4.1.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/apexcharts"></script>
<link href="https://unpkg.com/swiper/css/swiper.min.css" rel="stylesheet"/>
<div class="swiper-container">
<div class="swiper-wrapper">
<!-- Slide 1-->
<div class="swiper-slide">
<section class="india">
<p class="gas-header">INDIA</p>
<div id="demo-chart-1"></div>
</section>
</div>
<!-- Slide 2-->
<div class="swiper-slide">
<section class="canada">
<p class="gas-header">CANADA</p>
<div id="demo-chart-2"></div>
</section>
</div>
<!-- Slide 3-->
<div class="swiper-slide">
<section class="japan">
<p class="gas-header">JAPAN</p>
<div id="demo-chart-3"></div>
</section>
</div>
</div>
<!-- If we need pagination -->
<div class="swiper-pagination"></div>
</div>

AngularJS + bootstrap carousel help to display all the images

I have an array of objects, where I have the url of the image. I need to display these images in carousel:
<div class="item active">
<div class="row cst-carouselImg">
<div class="col-sm-3 col-xs-6" ng-repeat="image in pack.hotels.current.hotelImages | limitTo:'4'">
<a href="#"><img
ng-src="<?php
echo 'http://photos.hotelbeds.com/giata/';
?>{{image.path}}"
alt="Image" class="img-responsive"></a>
</div>
</div>
</div>
At this point I have only the first 4 pictures from the array. Next I display the next 4 images from the array:
<div class="item">
<div class="row cst-carouselImg">
<div class="col-sm-3 col-xs-6" ng-repeat="image in pack.hotels.current.hotelImages" ng-if="$index > 3 && $index <8">
<a href="#"><img
ng-src="<?php echo
'http://photos.hotelbeds.com/giata/';
?>{{image.path}}"
alt="Image" class="img-responsive"></a>
</div>
</div>
</div>
How can I display all the images using ng-repeat instead of manually adding <div class="item"> and setting manually $index?
Here i take some sample array you can modify it accordingly
var myApp = angular.module('myApp',[]);
myApp.controller('MyCtrl',function($scope, $timeout) {
$scope.hotelImages=[{id:1},{id:2},{id:3},{id:4},{id:5},{id:6},{id:7}];
$scope.loopCount=Math.ceil($scope.hotelImages.length/4);
$scope.getNumber = function(num) {
var arr=[];
for(i=0;i<num;i++){
arr.push(i);
}
return arr;
}
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.6/angular.min.js"></script>
<div ng-app="myApp" ng-controller="MyCtrl">
<div class="item" ng-repeat="i in getNumber(loopCount) track by $index">
Carousel :-{{i}}
<div class="row cst-carouselImg">
<div class="col-sm-3 col-xs-6" ng-repeat="image in hotelImages" ng-if="$index >=(i*4) && $index <(i*4)+4" >
image:- {{image.id}}
</div>
</div>
</div>
</div>
If I understood you correctly you are aiming at having a nested ng-repeat, one for the items and one for the images. Let me know if I misunderstood you or you need some clarifications. Please see this snippet below:
var app = angular.module("app", []);
app.controller('exampleCtrl', function($scope){
$scope.hotels= [
[
{
path: "hotel1 path1",
otherprop: true
},
{
path: "hotel1 path2",
otherprop: false
},
{
path: "hotel1 path3",
otherprop: true
}
],
[
{
path: "hotel2 path1",
otherprop: true
},
{
path: "hotel2 path2",
otherprop: true
}
],
[
{
path: "hotel3 path1",
otherprop: false
},
{
path: "hotel3 path2",
otherprop: false
},
{
path: "hotel3 path3",
otherprop: false
},
{
path: "hotel3 path4",
otherprop: true
}
]
];
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="app">
<div ng-controller="exampleCtrl">
<div class="item" ng-repeat="hotel in hotels">
<p>This is Hotel #{{$index+1}}</p>
<div class="row cst-carouselImg">
<div class="col-sm-3 col-xs-6" ng-repeat="image in hotel">
<a href="#">
<img ng-src="{{image.path}}" class="img-responsive" alt="(this is alt text)"/>
Image {{$index+1}}'s path: {{image.path}}
</a>
</div>
</div>
</div>
</div>
</div>