Error on calling react-modal in rails 4 app - ruby-on-rails

I'm having trouble using react-modal in my rails 4 app with a react-rails front end. I have already followed the steps in this SO question How to call react-modal from rails-assets.org in react-rails component and in this GitHub issue https://github.com/reactjs/react-rails/issues/510 but none of them seem to work.
This is the rails-assets gem in my Gemfile
source 'https://rails-assets.org' do
gem 'rails-assets-react-modal'
end
This is my application.js file
//= require react
//= require ./vendor/react-modal-v1.6.4
//= require react_ujs
//= require react-modal
The //= require ./vendor/react-modal-v1.6.4 call is a call to the compiled file for react-modal. I did this in accordance to the instructions provided in the github issue link above.
Finally, this is my component definition
var ModalTest = React.createClass({
getInitialState: function() {
return {
modalIsOpen: false
}
},
openModal: function() {
this.setState({modalIsOpen: true});
},
closeModal: function() {
this.setState({modalIsOpen: false});
},
render: function() {
return (
<div>
<button className="btn btn-primary" onClick={this.openModal}>
Open Modal
</button>
<ReactModal
isOpen={this.state.modalIsOpen}
onRequestClose={this.closeModal}
contentLabel="Modal"
>
<h1>Test Modal</h1>
</ReactModal>
</div>
);
}
});
I am getting the following error on the console:
Uncaught Error: react-modal: You must set an element with Modal.setAppElement(el) to make this accessible
What am I missing?
Thanks in advance, guys.

I found an answer from yachaka who posted in this GitHub issue for react-modal.
The script is loaded before the DOM, resulting in react-modal setting the parent element of the modal to document.body before it exists.
This can be fixed by adding the lifecycle method componentWillMount as follows:
componentWillMount: function() {
ReactModal.setAppElement('body');
}

Related

RAILS 6 - how to use EasyAutocomplete

I try the last hours to integrate EasyAutocomplete into RAILS 6. But not so easy.
What I did :
Install Javascript Package with yarn:
# yarn add easy-autocomplete
Add this in the file app/javascript/packs/application.js
import “easy-autocomplete”
Add this in the file app/assets/stylesheets/application.css
*= require easy-autocomplete
*= require easy-autocomplete.themes
Then start the Rails Server and refresh the Web Page.
Then try to use it. Go into the developer console and type :
var options = {
data: ["otto", "hans", "paula"]
};
$("#task_name_search_field").easyAutocomplete(options);
task_name_search_field was previously defined as id :
<input type="search" class="form-control" id="task_name_search_field">
I got this message:
TypeError: $(...).EasyAutocomplete is not a function
Any idea ?
I had the same problem. Turbolinks does not give access to the script, the code needs to be run after it is loaded, something like this:
document.addEventListener("turbolinks:load", function() {
var options = {
data: ["otto", "hans", "paula"]
};
$("#task_name_search_field").easyAutocomplete(options);
});
In order for the autocomplete to work, you need to add a script file to the application.js like this:
require("packs/youfile")
If it helps you, here is an example of my code:
document.addEventListener("turbolinks:load", function() {
$input = $("[data-behavior='autocomplete']")
var options = {
getValue: "full_name",
url: function(phrase) {
return "/search.json?q=" + phrase;
},
categories: [
{
listLocation: "cameras",
header: "<strong>Cameras</strong>",
}
],
list: {
onChooseEvent: function() {
var url = $input.getSelectedItemData().url
$input.val("")
Turbolinks.visit(url)
}
}
}
$input.easyAutocomplete(options)});
I suppose you wouldn't have included jquery in your application.js. You need to do explicitly as it doesn't get included automatically with rails 6 app.
I ran into a similar issue. I'm a n00b at Webpacker, but by default it doesn't seem to compile in the same order in which plugins are included.
To get around the issue I did this workaround which just wraps the plugin code in an anonymous jQuery function, like so:
(function($) {
//Eac plugin code
})(jQuery);
https://github.com/pawelczak/EasyAutocomplete/issues/200#issuecomment-212277620
Maybe there is a way in the configs to force compilation in the correct order. This looks promising https://stackoverflow.com/a/43005332/148390
Add script-loader to package.json then add
import 'script-loader!jquery/dist/jquery.min'
in app/javascripts/application.js
Check in your browser that $().jquery yields a proper result.

Uncaught TypeError: this.template is not a function Backbonejs

I am working in Rails with BackboneJS in handlebar templates.
I am getting a weird error here..
this is my header view
class App.Views.Header extends Backbone.View
className: "navbar-inner"
template: HandlebarsTemplates['app/templates/header']
render: ->
#$el.html(#template())
#
main application file is this
#= require_self
#= require_tree ./templates
#= require_tree ./views
#= require_tree ./routers
window.App =
Routers: {}
Views: {}
Collections: {}
Models: {}
initialize: ->
new App.Routers.MainRouter()
Backbone.history.start()
and my main router file is this
class App.Routers.MainRouter extends Backbone.Router
routes:
"": "index"
initialize: ->
#headerView = new App.Views.Header()
index: ->
$("#header").html(#headerView.render().el)
when I hit localhost:3000.. I got this error upfront.
Uncaught TypeError: this.template is not a function..
Am totally stuck in that any help will be appreciated Thanks
template: HandlebarsTemplates['header']
Template path should be only the template itself.
May that is version due to version or assets precompiled
It sounds like the Handlebars template in HandlebarsTemplates['app/templates/header'] either does not exist, has not been compiled, or there may have been an error while compiling it. That's the error you'd get if that value was null or undefined.
You might want to try setting a breakpoint in your browser's javascript debugger in the call to render, then use the debugger to check the value of this.template and see what's going on.

ActiveAdmin Select2 not working

I am using ActiveAdmin 1.0 (current master updated today). And have migrated from Chosen to Select2. I followed the directions at https://github.com/mfairburn/activeadmin-select2 but am noticing issues. If I navigate pages on the site, the css doesn't seem to be working. However if I am on a page and select the refresh button, the Select2 css shows up.
active_admin.js.coffee
#= require active_admin/base
#= require chosen-jquery
#= require_tree ./active_admin
#= require_tree .
#= require active_admin/select2
active_admin.css.scss
// SASS variable overrides must be declared before loading up Active Admin's styles.
//
// To view the variables that Active Admin provides, take a look at
// `app/assets/stylesheets/active_admin/mixins/_variables.css.scss` in the
// Active Admin source.
//
// For example, to change the sidebar width:
// $sidebar-width: 242px;
// Active Admin's got SASS!
#import "active_admin/mixins";
#import "active_admin/base";
//#import "chosen";
//#import "active_admin/chosen";
//body.active_admin {
#import "active_admin/select2/base";
//}
// Overriding any non-variable SASS must be done after the fact.
// For example, to change the default status-tag color:
//
// .status_tag { background: #6090DB; }
Any ideas why I have to refresh every page for the css to load? I have cleared cache and precompiled assets.
Sounds like this isn't a CSS issue, but an issue with your JS initialization and turbolinks. The problem lies on this line of code: https://github.com/mfairburn/activeadmin-select2/blob/master/app/assets/javascripts/active_admin/select2/select2.js.coffee#L15 which isn't compatible with Turbolinks, as the document.ready event isn't called when making page transitions - you can read about Turbolink's event lifecycle here: https://github.com/rails/turbolinks#events
My suggestion would be to probably override the file I linked to above by creating a assets/javascripts/active_admin/select2/select.coffee in your own app tree containing this code:
'use strict';
initSelect2 = (inputs, extra = {}) ->
inputs.each ->
item = $(this)
# reading from data allows <input data-select2='{"tags": ['some']}'> to be passed to select2
options = $.extend(allowClear: true, extra, item.data('select2'))
# because select2 reads from input.data to check if it is select2 already
item.data('select2', null)
item.select2(options)
$(document).on 'has_many_add:after', '.has_many_container', (e, fieldset) ->
initSelect2(fieldset.find('.select2-input'))
$(document).on 'ready page:load', ->
initSelect2($(".select2-input"), placeholder: "")
return
(notice the use of Turbolink's page:load event)

Rails 4 breaks Stellar.js after link

My rails 4 app breaks stellar.js after link_to.
I know that is something related with turbolinks.
I installed jquery.turbolinks and my js functions from uikit are all working now.
But the stellar.js still don't..
It works when I type the address in browser: 0.0.0.0:3000, but do not after clicking any link.
I am calling stellar.js from my assets/javascripts/my-js.js like this:
$(function(){
$.stellar();
});
I also tried with no success:
function initialize() {
$.stellar();
}
$(document).ready(initialize);
$(document).on('page:load', initialize);
Thank you
Your issue is most certainly related to Turbolinks. I have a feeling that when you call $.stellar() after a Turbolink request, the call has no effect since it's already attached to the window object and that doesn't go away during a the request. Try destroying it prior to initializing it again in the initialize function.
var initialize = function() {
$.stellar( 'destroy' );
$.stellar();
}
$(document).ready( initialize );
$(document).on( 'page:load', initialize );
You can also bind the destroy method to the turbolink before-cache event :
$(document).on "turbolinks:before-cache", ->
$.stellar('destroy')

javascript in rails not recognized

This is a fairly simple question but I can't seem to figure out why it's not working
I have this code:
$(".positive").numeric({ negative: false }, function() { alert("No negative values"); this.value = ""; this.focus(); })
which works when I put it in my view between <script> and </script>
However, when I copy and paste that formula to app->assets->javascripts-> page.js.coffee it doesn't work. I have even tried copy and pasting that code to JS2Coffee converter and pasting the coffee version of the code. Still no luck.
What am I doing wrong that my view does not recognize the javascript in my assets?
Here is the code in coffescript:
$(".positive").numeric
negative: false
, ->
alert "No negative values"
#value = ""
#focus()
my application.js has
//= require jquery
//= require jquery_ujs
//= require jquery.numeric
//= require_tree .
Your CoffeeScript generates the following JavaScript:
$(".positive").numeric({
negative: false
}, function() {}, alert("No negative values"), this.value = "", this.focus());
As you can see, it's not the same.
Please note some things:
You do not have to use CoffeeScript. You can use plain JavaScript if you want to.
If you want to use CoffeeScript, please read up on its syntax. Most importantly: in CoffeeScript, whitespace is significant.
Your codesnippet could look like this, in correct CoffeeScript:
$(".positive").numeric
negative: false
->
alert "No negative values"
#value = ""
#focus()
The reason that your code isn't executed when you put it through the asset pipeline, is that it will end up in the head of the document, instead of the body, and hence it will be executed before the browser has finished loading the DOM.
In other words - there isn't any element to fetch yet.
To solve this, wrap you code with JQuery:
$ ->
# Your code goes here
JQuery will make sure that your code is executed only once the DOM is ready for manipulation.

Resources