I just added the react-rails gem to my project and tried to add a react component to my index.html.erb file. I used the react component generator to make a simple message/text element, but it does not show up on my view after I deploy to Heroku, but it seems to render when I inspect the page. I have no idea why this isn't working.
Please look at the images I have attached. It looks like the javascript doesn't get compiled??
Body inspection part 2
index.html.erb code
<h2>Dashboard</h2>
<%= react_component('Message', text: 'hello') %>
<h3>Products TEST REACT </h3>
Message.jsx code
var React = require("react")
class Message extends React.Component {
render () {
return (
<div>
<div>Text: {this.props.text}</div>
</div>
);
}
}
Message.propTypes = {
text: React.PropTypes.string
};
module.exports = Message
HTML body inspection
I reverted to the git commit before installing react-rails and used the shakacode react-on-rails gem instead and got it to work
Related
I'm a Ruby on Rails newbie trying to use the Stimulus Component "Stimulus Carousel" on a Rails 7 app to have images of a flat displayed as a carousel.
Following the set up instructions from the official documentation triggered issues like the one mentioned on this other question about using Stimulus Components with Importmaps, so I tried adapting the answer to my problem by doing this:
./bin/importmap pin stimulus-carousel
This pinned the following in importmap.rb :
pin "stimulus-carousel", to: "https://ga.jspm.io/npm:stimulus-carousel#4.0.0/dist/stimulus-carousel.es.js"
pin "dom7", to: "https://ga.jspm.io/npm:dom7#4.0.4/dom7.esm.js"
pin "ssr-window", to: "https://ga.jspm.io/npm:ssr-window#4.0.2/ssr-window.esm.js"
pin "swiper/bundle", to: "https://ga.jspm.io/npm:swiper#7.4.1/swiper-bundle.esm.js"
I also generated the Stimulus controller:
rails g stimulus carousel
And wrote this in app/javascript/controllers/carousel_controller.js:
import { Controller } from "#hotwired/stimulus";
import { Application } from "#hotwired/stimulus";
import Carousel from "stimulus-carousel";
const application = Application.start();
application.register("carousel", Carousel);
// Connects to data-controller="carousel"
export default class extends Controller {
connect() {
super.connect();
console.log('Do what you want here.');
// The swiper instance.
this.swiper;
// Default options for every carousels.
this.defaultOptions;
}
}
I could check the stimulus controller was connected, but nothing changed visually on the flats#show page, the first image was still on top of the second. So I looked into Swiper documentation and added this line in the head of app/views/layouts/application.html.erb:
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/swiper#8/swiper-bundle.min.css"/>
Now, this did change the visual of the page: I've got the second picture far to the right of the first picture now, but this still isn't a carousel. I have tried adding this in the head too, but it didn't change anything:
<script src="https://cdn.jsdelivr.net/npm/swiper#8/swiper-bundle.min.js"></script>
Could someone please let me know how I should set this up for the carousel to display properly?
Here is what I have on the flats#show page in case it helps:
<div data-controller="carousel" class="swiper-container">
<div class="swiper-wrapper">
<% #flat.photos.each do |photo| %>
<div class="swiper-slide">
<%= cl_image_tag photo.key, class: "flat-image-show" %>
</div>
<% end %>
</div>
</div>
Thanks in advance!
I wanted to render a partial that contains a form inside of view from application js, I am reading the event of attached button without submitting because I need to process the headers of a file CSV before doing submit.
This is the function:
$(document).ready(function () {
$("#attached_attached_csv").change(function (e) {
if (e.target.files != undefined) {
var reader = new FileReader();
reader.onload = function (e) {
// this line isn't working - I try of many ways, but none are working
$("#text").html("<%= j render partial: 'layouts/form') %>".html_safe);
};
reader.readAsText(e.target.files.item(0));
}
return false;
});
});
I see also how any people using ajax, but I don't know how to use this for the trigger event of an attached button without submitting, I prob sending without html_safe but I obtain the string:
<%= j render partial: 'layouts/form') %>
My partial is "layouts/form", which is a file with extension html.erb. here share where I found the code for handle the event http://jsfiddle.net/FSc8y/2/, but it's not important the most important for me its render the embedded ruby form. Thanks in advance.
You can use rails syntax in your javascript files by adding .js.erb extension to the file name like my_file.js.erb.
I'm using the react-rails gem, and I'm having trouble figuring out how to load images from the asset pipeline.
I handle this currently by using the .js.jsx.erb extension, but as far as I know this is unconventional. (am I correct?)
Sometimes I just use an empty div and and set the div's background-image property as the image I intend to use.
What is the best way to go about loading images to react components when using react-rails?
There are three ways to import image...
1) If you are direct using jsx.erb or js.erb file...
var image_path = "<%= asset_path(my_image.png) %>"
OR
render: function() {
return (
<img src={"<%= asset_url('path/to/image.png') %>"} />
)
}
2) Passing as props Through .erb file to .js.erb or .jsx.erb file
in your .erb file
render_component('Component', img_src: image_url('the_path'))
in your .js.erb or .jsx.erb file
render: function() {
return (
<img src={this.props.img_src} />
)
}
3) Recommended: Use .js and .jsx file and render it using view file .html.erb
In view file example.html.erb
<%= react_component("Example", props: {}, prerender: false) %>
In .jsx file Example.jsx
import React, { Component } from "react";
import Image from "<IMAGE_PATH>/image.png";
export default class Example extends Component {
constructor(props, _railsContext) {
super(props);
}
render(){
return(
<div>
<img src={Image} alt="example" />
</div>
)
}
}
You need to register Example component. In your app > javascript > packs > application.js
import ReactOnRails from "react-on-rails";
import Exmaple from "<COMPONENT_PATH>/Exmaple";
ReactOnRails.register({
Exmaple
});
Source: github
The registration was working fine with the default HelloWorld app, but once I deleted the folder and created my own, it stopped working.
I made a new folder under app/bundles called posts with a startup folder.
In the startup folder, I'm registering the components like so:
import ReactOnRails from 'react-on-rails';
import PostContainer from '../containers/PostContainer';
ReactOnRails.register({
PostContainer
});
The PostContainer.jsx file is in the containers folder and it looks like this:
import React, { PropTypes, Component } from 'react';
export default class PostsContainer extends React.Component {
render() {
return (
<div>
<Header />
<PostList posts={this.props.posts} />
</div>
)
}
}
My webpack.config.js file looks like this:
entry: [
'es5-shim/es5-shim',
'es5-shim/es5-sham',
'babel-polyfill',
'./app/bundles/HelloWorld/startup/registration',
],
I tried changing the HelloWorld to posts or Posts, but it did not work.
Am I supposed to have a file called webpack.configure.build.js? Or is the webpack.config.js the file I need to edit?
Any help would be appreciated!
Did you add the component to the erb view file with the associated props passed in? You would need to add the props within your Posts controller or whichever controller is rendering your Posts view. I'm pretty sure you would then need to add a line in your webpack config:
config: {
'webpack-bundle': [
'...',
'./app/bundles/Posts/startup/registration'
]
}
Then in your view:
<%= react_component("PostsContainer", props: #posts_props, prerender: false) %>
Also make sure in your layout file you have:
<%= javascript_pack_tag 'webpack-bundle' %>
Note: PropTypes should be imported from the prop-types package now. The react team plucked that package out of the react core as of recent.
For my project, I am using Ruby on Rails and Angular and I have a haml file present in /project_name/app/assets/javascript folder. I want to call a ruby class from the haml file but unfortunately I am not able to do that.
.small-12.columns
.booking-time
%span.bold
- if ABC::D.data(:hide_hours_field) #ruby code
{{ item | timeformat }}
- else
{{ item | differentTimeFormat }}
Whenever I start the server, it's is showing it can't access the ruby class. I can easily access the ruby class in other haml files but not the one present in javascript folder. Can anyone help me here?
Disclaimer: I'm bad at Angular (and didn't even touch version 2). What follows is not a best practice or anything.
So, you need to configure your angular view with some knowledge from ruby side. You can't conditionally render it and you can't call ruby from angular controllers (obviously). I suggest smuggling data via window object.
In an appropriate view in your application, put this JS snippet.
<script type='text/javascript'>
window.jsEnv = {
hide_hours_field: <%= ABC::D.data[:hide_hours_field] %>
}
</script>
Then you can reference that via $window object in angular
Controller
function MyController($window) {
this.hideHours = function() {
return !!$window.jsEnv.hide_hours_field;
}
}
MyController.$inject = ['$window'];
angular.module('myApp').controller('MyController', MyController);
View
.small-12.columns(ng-controller='MyController as vm')
.booking-time
%span.bold(ng-if='vm.hideHours()')
{{ item | timeformat }}
%span.bold(ng-unless='vm.hideHours()')
{{ item | differentTimeFormat }}
I suggest you use angular constant instead of window then you can use it as service:
// index.html
<script type="text/javascript">
angular.module('myApp').constant('CURRENT_USER', #{current_user.to_json})
</script>
// controller
function ApiConsoleController($scope, CURRENT_USER) {
console.debug(CURRENT_USER)
}
Also, you can try to use angular-rails-templates
// application.rb
config.angular_templates.ignore_prefix = %w(
angular/components/
angular/shared/
angular/directives/
angular/validators/
)