I develop a PHP web app. The UI is built with Twig templates.
I've started to add some new (and replace some existing) forms with ReactJS components. I like the approach and I am happy with the results.
The application uses Bootstrap 4. A couple of the ReactJS components wrap/use the Bootstrap 4 modal.
I show/hide the modals with JQuery inside the React components. I can't work out any other way of doing it.
$("#myModal").modal('show');
I know you're supposed to avoid JQuery in React, but is there another way of opening/closing the modals without JQuery? A couple of lines of JQuery per component seems like the simplest approach.
I tried to open close the modals by setting state and then applying styles, but it doesn't work because I still need to set styles on the 'parent' body outside the React component.
It's better to avoid jQuery in React Components.
For your bootstrap modals, you can convert them to ReactBootStrap components.
You can achieve the same thing with this one as well.
Moreover you can use ref={refName} on the modal and access the DOM element for the modal and use the .modal() function provided by Bootstrap to show/hide the modal.
Like below:
const modalRef = useRef(null);
const handleShowModal = () => {
$(modalRef.current).modal('show');
};
const handleHideModal = () => {
$(modalRef.current).modal('hide');
};
The Modal Div should be <div ref={modalRef} like this.
Related
I want to mix basic HTML generated by Php and VueJS components without having to use VueJS all the way down to the lowest dom leaf.
The parent layout has the Vue app applied all the headers navs assides etc are Vue components and the main content on most pages are still plain HTML generated by PHP.
I want to upgrade small parts of the main content with Vue components but I cant use them once HTML has been used:
Php script generates the entire dom
<div id="app"> VueJS instance mounts here.
<Cats>This component works perfectly here.
<div id="main Content">More HTML content generated by PHP.
<Cats> Cats does nothing here.
<Cats> works perfectly fine in the upper DOM but after rendering some basic HTML the app will no longer populate components further down.
Php can render JS in a script tag but it's unable to use any imports.
Is there any way to get the Vue instance to treat all <Cats> tags as the Cats component regardless of where it is written on the page?
So far I have tried:
async components.
portals using mounting portals.
creating another Vue instance and mounting it to another ID.
Any ideas?
EDIT: The things I tried previously may be been blocked by the mishmash of multiple UI modernization attempts in this monolith I have inherited.
So I would not rule those out for others facing this situation.
If you are dynamically passing the template which is coming from an API or from any other source into your Vue instance. There is a way to access that via v-html attribute but before using that please have a look at note below.
Note that the contents are inserted as plain HTML - they will not be compiled as Vue templates.
Hence, As you are trying to bind/render the Component itself and it's not a plain HTML. So it will not processed by Vue's template compiler.
Possible solution is that you can get a component name and props from your PHP API instead of whole HTML template.
You can also achieve the same by using Vue compile option. Here is the demo :
Vue.component('Cats', {
props: ['msg'],
template: '<h3>{{ msg }}</h3>'
});
// Template coming from PHP
const template = `<div id="main Content"><Cats msg="Meow... Meow..."></div>`
var app = new Vue({
el: '#app',
data: {
compiled: null
},
mounted() {
setTimeout(() => {
this.compiled = Vue.compile(template);
})
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<Cats msg="Meow...">
</Cats>
<component :is="compiled"></component>
</div>
In the end, I had to manually add a JS file to the build configs containing a global window.ExtraVue with a setup function like so:
import Cats from 'files/Cats.vue';
window.ExtraVue = {
setup: function(data) {
new Vue({
el: '#extra-vue',
data: data,
components: {
Cats
},
template: '<Cats/>'
})
}
};
The setup function is then called at the very end of the PHP script.
<script>window.ExtraVue.setup(<?=json_encode($array)?>)</script>
The setup function can now create a new Vue instance for each component that needs to be out on its own.
Ideally, it would be great if VueJS could just replace matching tags with components.
I'm stuck using a theme in WordPress for a client where the header is horrible in responsive view. I can work with desktop widths but anything below 768px needs to have an entirely different markup because of the clients demands -- any attempt to try to do this via CSS has led to even more UI disasters. My hope was to utilize jQuery's .html() functionality to swap out Bootstrap grid elements at < 768px. Here's a snippet example -- say I needed to move the logo from a far right position in desktop to the first element on the left in a header. I'm using the theme's declarations for the dynamic logo correctly:
if($(window).width() < 768) {
$('.top-bar').html('<div class="col-md-3"><?php vg_ebuilder_display_logo_sticky(); ?><div class="logo-inside"><?php vg_ebuilder_display_top_logo(); ?></div></div>');
}
But this returns commented out PHP:
<!--?php vg_ebuilder_display_logo_sticky(); ?-->
and
<!--?php vg_ebuilder_display_top_logo(); ?-->
So, maybe two questions here: is there a way to add dynamic PHP like this in WordPress via a jQuery .html() function on $(document).ready and, assuming it could, would it indeed be dynamic if loaded after the DOM?
No. PHP runs on the server, not the client. The javascript would need to make a call to an endpoint that would perform the php logic, return a response, and that response put on the page. Inserting php on the client will not be invoked.
I can't 'comment' a suggestion to you as my reputation isn't yet 50, so hopefully this is the right answer. I found this worked for me with a similar issue in Joomla (Q48891999).
In the div you want to change, add a unique class, e.g. "builder".
Then, if you need to, write a new css class or classes starting with
#media (max-width: 767px) {
.your_new_class {
}
}
- but not using the name 'builder' for the new class - in your custom css file for the div you want to change.
Then use jquery .addClass to apply the css class to your div in your index.php. Something like this:
<script>
$( ".builder" ).addClass( "the_class_you_want_to_apply another_class" );
</script>
The spaces between the parentheses and the double quotes are deliberate, as used in the examples on the jquery website.
In my case, I added this to the bottom of my index.php just before the closing body tag.
You may need to have more than one of these scripts to apply to different elements.
So, I have that WordPress website on which I installed a template (Zoo). My problem is that I want the whole site to be in French, and there are three buttons in that template which title tag is coded deep in a js file that is inside a plugin which has been integrated to the template.
These are my first steps as a web developer (I come from C++) and I'm having quite a hard time understanding what is missing in the files, but I understood a few things by looking around.
So I made a child theme. This is the functions.php file. I think it works fine, but here it is in case I am doing it wrong :
<?php
function removethosedamntooltips(){
wp_register_script('removetooltips', get_stylesheet_directory_uri() . '/js/removetooltips.js');
wp_enqueue_script( 'removetooltips' );
}
add_action('wp_enqueue_scripts', 'removethosedamntooltips');
This is the aforementioned removetooltips.js file. I believe I have to call for a button hover because the template is single-page parallax and the buttons I want to modify are not visible until you click another button which allows for another display without sending the browser to another URL (if I remove line 2 and the closing brackets that go with it, it doesn't work anyway). Also, those tooltips appear only on mouse hover, so it seems a good idea :
jQuery(document).ready(function(){
alert("jQuery!!");
jQuery("button").hover(function(){
alert("jQuery!!");
jQuery(".mfp-arrow-left").attr("title", "Précédent (flèche gauche)");
jQuery(".mfp-arrow-right").attr("title", "Suivant (flèche droite)");
jQuery(".mfp-close").attr("title", "Fermer (Esc)");
});
});
The first alert displays after the page is loaded, but the second one does not show up. The tooltips (button title) still show up in English.
A piece of information that might be useful to solve this problem (I'm only 2 days into reading stuff about JavaScript and jQuery so I don't really know): I had to use jQuery instead of $ or the console would tell me that $ is an unknown function. Do I need to somehow include the jQuery framework in my file (if so, where and how ?), although a calling for the jQuery library already shows up in the header ?
If you provide a solution that will remove the tooltips instead of replacing their content, I will be happy enough.
Thank you in advance !
Instead of using
jQuery("button").hover(function(){...});
You should find the container in which all buttons are placed or just use body
and use jquery .on() method. As far as I know it'll work.
so your complete code will be like this
jQuery(document).ready(function(){
alert("jQuery!!");
jQuery("body").on("hover", "button", function(){
jQuery(".mfp-arrow-left").attr("title", "Précédent (flèche gauche)");
jQuery(".mfp-arrow-right").attr("title", "Suivant (flèche droite)");
jQuery(".mfp-close").attr("title", "Fermer (Esc)");
});
});
Explanation:
Using .on() method binds the event with dynamically created elements too. As you mentioned in your question that buttons are not created until another button/link is clicked.
Edit: Tested this one and its working. I've removed the second alert because with that you won't be able to test.
How would I put this in my cakephp default.ctp file?
Im pretty novice at cakephp as ive just started using it.
<script>
$(function()
{
$('#slider-id').codaSlider();
});
</script>
Thanks, in advance.
Although your question is too vague to answer in its current state, you should have a look at the JsHelper,especially Js->buffer(). This allows you to append script in your views and output them all at once in your layout.
http://book.cakephp.org/2.0/en/core-libraries/helpers/js.html#working-with-buffered-scripts
open the app/View/Layout/default.ctp file in your favorite code editor
add the following between your <head> and </head>:
<script>
$(function()
{
$('#slider-id').codaSlider();
});
</script></li>
In CakePHP 2.x there are now things called blocks, and blocks are just chunks of output stored in memory until they are fetched for output.
There use to be a $scripts_for_layout variable that you could put your script into, but now we use the $this->fetch('scripts'); to get any JavaScript needed for the Html.
There are a few ways to inject JavaScript into the scripts block using the HtmlHelper.
To add it to the block, and this can be done in Views or Layouts. Just run this code before you fetch the block.
$this->Html->scriptBlock("$('#slider-id').codaSlider();",array('inline'=>false));
To output the scripts in your layout is easy.
$this->fetch('scripts');
The advantage of this approach is you can add JavaScript from multiple places in CakePHP, but they will be outputted in the layout at the location you desire.
Currently working with ZF and ZendX_JQuery.
As I understand, script links to Google's CDN JQuery are only included in the <head> section of a view if ZF JQuery is referenced in some way in the MVC.
However, I'm working with 'Cloud Zoom', a JQuery library for image zooming.
The view I wish to include Cloud Zoom in has no reference to JQuery, and therefore the script links are not included in the head. How can I make ZF include the script links in the head section of the page without explicitly including any ZF JQuery references in the MVC?
from http://framework.zend.com/manual/en/zendx.jquery.view.html
To access the javascript we have to
utilize the jQuery() functionality.
Both helpers already activated their
dependencies that is they have called
jQuery()->enable() and
jQuery()->uiEnable()
i have this code in my layout
if ($this->jQuery()->isEnabled()) {
$this->headScript()->appendFile('/scripts/jquery.ui.datepicker-it.js');//localizazione di DatePicker
echo $this->jQuery()->setRenderMode(ZendX_JQuery::RENDER_JAVASCRIPT | ZendX_JQuery::RENDER_JQUERY_ON_LOAD);
}
so i guess you have to do something like $this->jQuery()->enable()->enableui()