I want to create a dygraph graph within the Bootstrap card body's second column (it just looks nice and clean). The div used by dygraph is graphdiv. I am using this.$refs.graphdiv to try to access it from within my vue script.
If I move the graphdiv <div> outside the card div then it works (see the comment). Why will the dygraph not work within the bootstrap card? Is it just one of those compatibility things one must log with the developer and wait for a fix?
<template>
<div>
<div class="card">
<div class="card-header">HEADER</div>
<div class="card-body">
<div class="row">
<div class="col-sm-3" style="width: 100%">
</div>
<div class="col-sm-9">
<div id="graphdiv" style="width: 100%" ref="graphdiv"></div>
</div>
</div>
</div>
</div>
</div>
<!--Comment: IF I PLACE IT HERE IT WORKS -->
</div>
</template>
Here is a reduced version of script:
<script>
import Dygraph from "dygraphs";
export default {
methods:{
plot_chart_series() {
//dataset = my data that I want to plot
const g = new Dygraph(this.$refs.graphdiv, dataset, {//options});
}
}
};
<script>
P.S.
My reason for using dygraph is I want to plot a dataset which is rather large (+-30000 datapoints), chart.js and Apexchart cannot manage that (I spent the better part of 3 hours trying to get them working). If there is no fix for my issue above, which other graphing libraries are there which are Vue friendly which can handle large datasets?
Workaround
I have managed to find a work-around and I can at least relatively narrow the problem and say that I do not think it is bootstrap.
<div class="card" ref="carder">
<div class="card-header">Graph</div>
<div class="card-body">
<div class="row">
<div class="col-sm-3">
<button>A_BUTTON</button>
</div>
<div class="col-sm-9">
<div ref="graphdiv" style="width: 100%"></div>
</div>
</div>
</div>
</div>
The above code snippet worked for me.
Changes to original:
I had an id="some_id" property in the containing parent div which I removed.
The entire card was wrapped in another div. This div had a ref="some_ref" property which I used from the Vue script to toggle the visibility. I did this with this.$refs.some_ref.style.display = "block"; & this.$refs.some_ref.style.display = "none";. I changed it to the following this.$refs.some_ref.style.visibility = "hidden"; and just changed the hidden to visible when I wanted to show the card. (It does not bother me that the hidden element still consumes space)
If I revert change number 2 above to the original then it fails to display. I still cannot explain it but it works.
Related
Github repo (https://github.com/teke85/Luxury_living/tree/add-home-page)
In my bootstrap project I successfully managed to retrieve data dynamically from a javascript object. I noticed that the last row is not aligned correctly. how do i fix this or what could have caused the misalignment? Please note, The issue wasn't there before I fetched the data dynamically using Javascript.
If you are using the newest version, you can do something like this:
<div class="container">
<div class="row">
<div class="col">
Content for column 1
</div>
<div class="col">
Content for column 2
</div>
</div>
</div>
I have a table structure which is made out of distinct blocks which cannot be brought into the same block, such as this - only much larger.
The structure of this ideally needs to stay the same.
<div class="dynamicList">
<div class="header">
<div class="item">col1</div>
<div class="item">col2</div>
</div>
<div class="row">
<div class="item">Learn JavaScript</div>
<div class="item">test message</div>
</div>
<div class="row">
<div class="item">Build something awesome</div>
<div class="item">medium message</div>
</div>
</div>
I want a way to be able to dynamically size the columns in the row to auto fit to the text so that the largest text column width is used for all the others of the same column. On the top is how it looks, at the bottom is how I want it to look.
I was hoping I could get away with just using CSS for this, however I feel I might need some JavaScript too. I am using React, so thought about using useRef hook, but didn't know how well this would perform with a really large table.
What is the best way to calculate this width and then use it across all columns of the same index?
Here is a JS fiddle showing the problem.
https://jsfiddle.net/og8kz3hp/65/
I have a website that i am trying to personalize and I am trying to use the AnimatedModal.js framework. I have been able to display some content in one modal, but when it comes to make several modal it gets tricky, because there is just one ID. My question i, how can i use the same ID and change the content for other modals(demo03,demo04..etc.), in order to personalize each.
I will put some code in order to understand the problem
I have been reading the documentation but I am still stuck in this problem.
<!-- single work -->
<div class="col-md-4 col-sm-6 ads graphics">
<a id="demo02" href="#animatedModal" class="portfolio_item">
<img src="img/portfolio/03.jpg" alt="image" class="img-responsive" />
<div class="portfolio_item_hover">
<div class="portfolio-border clearfix">
<div class="item_info">
<span>Should open here </span> <em> ads / Graphics </em>
</div>
</div>
</div>
</a>
</div>
<!-- end single work -->
Then I have the demo where it displays the content of the modal, where it has the #animatedmodal ID
<div id="animatedModal" class="popup-modal ">
<!--THIS IS IMPORTANT! to close the modal, the class name has to match the name given on the ID -->
<div id="btn-close-modal" class="close-animatedModal close-popup-modal">
<i class="ion-close-round"></i>
</div>
<div class="clearfix"></div>
<div class="modal-content ">
<div class="container">
<div class="portfolio-padding" >
Hello World
</a>
</div>
</div>
</div>
</div>
this is my Js file where there is just one element assigned to it, to avoid showing the same content into all different classes.
$("#demo02").animatedModal();
I don't think it can be done without hacking the plugin.
As a matter of fact, the script jQuery.animatedModal ALWAYS TARGETS the page element which has id="animatedModal"
You can see the plugin source code here:
https://cdn.jsdelivr.net/npm/animatedmodal#1.0.0/animatedModal.js
...
//Defaults
var settings = $.extend({
modalTarget:'animatedModal',
...
Here is the AnimatedModal reference:
https://joaopereirawd.github.io/animatedModal.js/
At the bottom of the page, I can't see any OPTION regarding how to specify a different target, all options are about styles and animation features.
At this point, I think the only way to allow multiple modals on the same page is to rewrite the plugin, but I'm pretty sure you don't want to choose this way.
My problem is related to placing the same component with different parameters on the same page. In this case it is a component containing a chart from a third party Javascript library (D3JS) which needs an HTML id attribute to locate and modify the component's HTML contents.
Now this id attribute should contain a unique string for each chart placed on the page, and if I directly set it as a string from the parent component it works just fine:
<my-chart id="gaugeChart0"></my-chart>
The reason it works is I guess, because the id attribute exists right at component creation time and whatever code is trying to access it can do that right away.
However this chart is in turn embedded into a bootstrap 4 card layout, like so:
<div class="row">
<div class="col-6">
<div class="card">
<div class="card-body">
<div class="row">
<div class="col-5">
<my-chart id="gaugeChart0"></my-chart>
</div>
<div class="col-7">
... Some other widgets ...
</div>
</div>
</div>
</div>
</div>
<div class="col-6">
<div class="card">
<div class="card-body">
<div class="row">
<div class="col-5">
<my-chart id="gaugeChart1"></my-chart>
</div>
<div class="col-7">
... Some other widgets ...
</div>
</div>
</div>
</div>
</div>
</div>
Now to make it more convenient (and to easily bind to click events to the whole block etc.) I would like to extract the whole part beginning with <div class="card"> into a new component.
Let's say I call this new component WidgetContainerComponent which contains the chart as well as the bootstrap card layout including the other widgets defined there.
The resulting code when using this wrapper component would be:
<div class="row">
<div class="col-6">
<widget-container chartId="gaugeChart0"></widget-container>
</div>
<div class="col-6">
<widget-container chartId="gaugeChart1"></widget-container>
</div>
</div>
In order for that to work the WidgetContainerComponent has an input field
#Input() chartId: string;
that can be set.
What I want to do then is to set the id attribute of the MyChartComponent to the string that has been set to chartId:
<div class="card">
<div class="card-body">
<div class="row">
<div class="col-5">
<my-chart [id]="chartId"></my-chart>
</div>
<div class="col-7">
... Some other widgets ...
</div>
</div>
</div>
</div>
But this does not work, as angular adds a prefix to the id attribute which results in something like ng-reflect-id.
I also tried setting the attribute with [attr.id] as described here and here:
<div class="card">
<div class="card-body">
<div class="row">
<div class="col-5">
<my-chart [attr.id]="chartId"></my-chart>
</div>
<div class="col-7">
... Some other widgets ...
</div>
</div>
</div>
</div>
This results in the MyChartComponent having a straight id attribute, but it seems to be only added at a later stage within the lifecycle of the component.
I also tried to initialize the chart within the MyChartComponent only in ngOnInit and ngAfterContentInit, but this does not work as well.
Any suggestions or ideas are very welcome!
So I found a solution to this problem. The problem was twofold:
The first problem was related to the requirement of having a genuine id attribute in contrast to the attribute name prefixed with ng-reflect- by angular.
What I didn't know is that from Angular 4, this prefix gets added to any attribute which is declared as an #Input variable for the component in development mode (for an in-depth explanation see this post).
The solution to this problem was to write [attr.id]=chartId instead of [id]=chartId. The reason is that in this case I needed to set an HTML Attribute, however using the square brackets notation I created a Property Binding. In order to dynamically set an HTML Attribute via the property binding syntax you have to add the prefix attr. to the attribute's name.
For a good overview regarding all valid binding syntaxes see the Angular Docs.
Specifically to review how to do attribute binding see this section.
The second problem was that I tried to access the id attribute of the component when it has not yet been created. This problem is related to the lifecycle hooks of Angular, where there are different stages. For a good overview of Angular's lifecycle hooks, see this page.
Because I didn't know it myself in detail, I will elaborate it here shortly.
Angular comes with a fixed set of lifecycle hooks which are called each time a component is set up and are also called in a predefined order. The hooks are defined as follows:
constructor
ngOnChanges
ngOnInit
ngDoCheck
ngAfterContentInit
ngAfterContentChecked
ngAfterViewInit
ngAfterViewChecked
ngOnDestroy
_
Important to note is that elements created or prepared in one step can only be accessed in any of the subsequent steps. In my case I put all the code for the initialization of the chart into the ngAfterContentInit hook, however the component is only fully loaded when ngAfterViewInit is called.
Finally the solution was to put the pre-initialization code into the constructor and to place the chart initialization code into the ngAfterViewInit method. At this stage the id attribute had been created properly and could be accessed by the chart.
I attempt to add a background image and use cover to let the browsed resize the image. However the image is very small and doesn't cover the whole background.
I am new to angular so I have a very small idea about how this works.
Also, the search bar isn't in the middle despite using zurb to manage spacing for me.
Here is what the page looks like
Here is the code:
<div >
<!-- Above fold -->
<div class="row">
<div id = "backgroundImage" class="large-12 small-12 columns" ng-style="{'background-image':'url(img/mainBackground.png)','background-size' : 'cover'}">
<!-- search bar -->
<div class="row">
<!--empty -->
<div class="large-3 small-3 columns">
</div>
<div class="large-6 small-6 columns">
<input type="text" id="searchBar" ng-style="{'width': '50%'}">
</div>
<!--empty -->
<div class="large-3 small-3 columns">
</div>
</div>
</div>
</div>
</div>
Adding on to #Marko's response, you are using Angular to style an attribute, but the styles you are providing are just static. Angular's ng-style attribute is intended to be used when you have dynamic styles that you want to apply at runtime based on a given condition. You aren't doing that. You're simply providing static styles that you want to be applied, inline. That's not really considered a best practice. It would be better to just use a static css stylesheet to do what you want.
That being said, the issue you're facing is purely a CSS one, not an angular-specific one. You just need to debug your style on your #backgroundImage div and you'll eliminate a lot of the complexity involved in using ng-style.
Here's a good tutorial on using full-page css background images: http://css-tricks.com/perfect-full-page-background-image/