ReactJS componentDidMount does not behave as expected with Bootstrap - javascript

I want to call $(dom).popover() on a rendered DOM. So I have:
module.exports = React.createClass({
componentDidMount: function() {
$(this.getDOMNode()).popover();
},
render: function() {
return ( // My DOM );
}
})
This returns error: TypeError: $(...).popover is not a function. BUT if I put a delay in the componentDidMount, then it works, i.e.:
componentDidMount: function() {
var _this = this;
setTimeout(function () {
$(_this.getDOMNode()).popover();
}, 250);
}
How can I accomplish the same thing without using setTimeout?

Try placing your jquery code inside a $(document).ready().
E.G. :
componentDidMount: function() {
var _this = this;
$(document).ready(function() {
$(_this.getDOMNode()).popover();
});
}
Edit #1: In response to comment: "You should also explain why" – Rohit Gupta
If you ask why too much, it will destroy the wonder of it all.
I joke. I came across the answer because I was having the same problem as the OP. I was using jQuery to reinitialize a Materialize.css accordion widget(which uses jQuery) in my componentDidMount function--or at least I was trying. But it wasn't working like I figured it should.
Then I came here, saw the OP had tried using setTImeout, and it worked; I tried it; it worked for me--even at 1ms--then I had the idea that slapping in a document(ready) function might work since basically it does something similar to the componentDidMount lifecycle function. $(document).ready listens for the entire document to load before it runs anything in the callback--compondentDidMount listens for the component to mount before it runs anything.
When you put a $(document).ready function inside the componentDidMount function(and put all the stuff into the former that which would typically only be in the latter), it will delay the code in the componentDidMount function until the whole document is loaded rather than just the component that the componentDidMount function resides in. The popover function acts on some element of the page that has yet to load. With the OP's original code you can manually call the popover event in the console after the page has loaded, which will then initialize the effect, which implies that the element that is needed for the popover does not exist when componentDidMount is called, but does exist after the page is fully loaded--which is why $(document).ready works: that is when its callback is triggered.
That is my theory atleast :) Any alternative theories of why it works?

if you defined a import literal in your code, please try removing.
// import * as $ from "jquery";

Make sure you have correctly included your js files like this:
<html>
<body>
...
<script src="jquery.js"></script>
<script src="bootstrap.js"></script>
<!-- Your js file that starts React app -->
<script src="myapp.js"></script>
</body>
</html>

Related

How to select new loaded elements in jQuery without any event

I am working on a jQuery project which a part of page is loaded by choosing different options usign load() method.
I have this line in my application:
$('.pe').myFunction();
This code must be executed without any event. So I can not use any code like this:
$(document).on('click','.pe',function(){...});
It works well on all preloaded elements with pe class.But it does not work on new loaded contents which have same class.
Can you help me please?
The arguably correct way of doing it is using $(document).on('.pe','click',function(){...});; however, I did program a fair amount before I discovered that. So, I know there are a couple of work around. I'd use a class to mark an item as 'completed' after adding a click event.
If you have any 'hook' to know when the new html is added you can simply call a function that instead of using an interval.
Note regarding the question: you did say no events and this uses no events.
//Simulating ajax loading
setInterval(function () {
$(document.body).append('<button class="clickable">So clickable!</button><br />');
},1000);
//Your code
setInterval(function () {
$(".clickable:not(.completed)").click(function () {
console.log('works!');
}).addClass("completed");
},10);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div>
<button class="clickable">So clickable!</button>
</div>
Finally I found the answer. I just put the same code inside the loaded page.
// New page which will be loaded with its all contents ...
<script>$('.pe').myFunction();</script>

Javascript not working on page refresh

So I have this block of code:
$(document).ready(function() {
planSelectionForm.init($("form#new_account"));
});
And when I link to this page it works as expected. But when I refresh from the browser it doesn't get triggered. This seems like a common problem. Just for the record I'm using turbolinks. Any help on why this is happening would be great!
The only solution I could find after getting this problem was wrapping my script with:
document.addEventListener("turbolinks:load", function() {
planSelectionForm.init($("form#new_account"));
});
Wrap your .onready() functions into a function called initialize. The point, is to seperate the event-driven function calls such that the event driven function call calls a global function.
In there, add to your body or another element that supports onload.
$(document).ready(function() {
initialize();
});
function initialize()
{
}
<body onload="initialize(); return;"> </body>
Also, for Caleb, in my experiance, I believe jQuery ready events only get executed on either a fresh load, or a ctrl+f5 cache reload.

Where should I initialize select when using Materialize and Meteor?

I'm trying to use Materialize Forms on Meteor. On its Materialize's page it says I should init the "select" input field like this:
$(document).ready(function() {
$('select').material_select();
});
I've tried calling this on Meteor.startup, Template.body.created - nothing worked. I get the following error:
undefined is not a function (evaluating '$('select').material_select()')
Where should I initialize it?
Use the template's .rendered callback
<template name="hello">
<select><option>...</option></select>
</template>
Then you can have this in your js file
Template.hello.onRendered(function() {
$('select').material_select();
});
The template is added to the body most likely after rendered has already fired so thats why the body rendered didn't work. If you use .created the DOM hasn't rendered yet.
Akshat's answer is correct but if it still doesn't work for you, there might be a problem with subscription not fired yet or not every needed part of DOM beeing rendered. Use afterflush then.
Template.listing.onRendered(function () {
var template = this;
template.subscribe('listOfThings', function () {
Tracker.afterFlush(function() {
template.$('select').material_select();
});
});
});
Here is a conversation about that: https://github.com/meteor/meteor/issues/4401#issuecomment-103340262
And the docs: http://docs.meteor.com/api/tracker.html#Tracker-flush

Passing reference to object javascript function

I have a function that gets called during a control update where 'This' is passed so the function knows what control is updating. I am also calling the function at page load to get initial values but sending document.getElementById() doesn't seem to work. What should I be passing here?
For example:
<script type="text/javascript">
window.onload = function () {
alert("Got to window.onload");
materialSelectionChange(document.getElementById('SquaresDropDownList'));
};
</script>
in the js file...
function materialSelectionChange(obj) {
alert("Got into function");
}
Also, it does fire the js function on change properly
EDIT
The problem seems to be the load time of the JS document. The function wasn't successfully being called at that point because apparently the JS file hadn't finished loading. Likely because of window.onload. It works if I move the function into the page rather than in the JS file. Is there a way I can add delay so I know the page and it's components are fully loaded?
You are not delegating for window load event, you are invoking it, also your missing quotes around the id:
window.onload = myFunction(document.getElementById(typeSelect));
Try wrapping it around:
window.onload = function() {
myFunction(document.getElementById('typeSelect')); //id in quotes
};
EDIT
You must take care of js file import, import must be first before invoking the function within:
<script src='your-script-file.js'></script>
<script type="text/javascript">
window.onload = function () {
materialSelectionChange(document.getElementById('SquaresDropDownList'));
};
</script>
<select id="typeSelect" onchange="myFunction(this)">
window.onload = function(){
myFunction.bind(document.getElementById('typeSelect'));
}
The problem seems to be the load time of the JS document. The function wasn't successfully being called at that point because apparently the JS file hadn't finished loading. It works if I move the function into the page rather than in the JS file. Is there a way I can add delay so I know the page and it's components are fully loaded?

weird jQuery JSON function... whats going on here?

Im browsing the flot examples here http://people.iola.dk/olau/flot/examples/turning-series.html
(view source once there)
I came across this :
<script id="source" language="javascript" type="text/javascript">
$(function () {
var datasets = {
"usa": {...
The $(function() part. I get that its an anonymous function, I dont get why it is used here. Wouldnt this be just as good :
<script id="source" language="javascript" type="text/javascript">
var datasets = {
"usa": {...
I checked over at the jQuery docs (http://api.jquery.com/) and found no special use for function()
$(function () {
Is for executing the code when the DOM is ready, it's a document.ready handler in jQuery, the same effect as:
$(document).ready(function () {
You want to run certain things on document.ready so that the elements are there, for example if you're using $(".class") as a selector, you wouldn't want that code to run until the DOM was fully loaded, so the elements you're looking for are there, ready to be found by the selector...this means your code would always work, even if it's in the <head>.
For documentation, look at jQuery(callback) in the API.
This is shorthand for $(document).ready(handler) which waits until the DOM is fully loaded before running the anonymous function.
In jQuery, $(function() { is shorthand for $(document).ready(function() {.
Yes, your 2nd part would work equally well, but the first one guarantees that the entire DOM for the page is loaded before it is executed.

Categories