I am trying to add simple controller to view that uses preact component in ruby rails - ruby-on-rails

I am trying to add simple controller to view that uses preact component in ruby rails. It just shows hello world just a basic program just trying to use a preact component in rails.
There is not much available for such thing to try I have been searching for quite a time now but no luck. I am following this https://github.com/UseHover/preact-rails to perform this.
application.html.erb
<title>Helloworld</title>
<%= javascript_include_tag 'application', 'data-turbolinks-track': 'reload' %>
</head>
<body>
<%= yield %>
<%= javascript_pack_tag 'application' %>
</body>
The view where I call the component.
<%= preact_component('Button', { type: 'submit', label: 'Get started!'}) %>
Package.json
{
"name": "helloworld",
"private": true,
"dependencies": {
"#rails/webpacker": "^4.0.7",
"preact": "^8.5.2",
"preact_ujs": "^0.1.1"
},
"devDependencies": {
"webpack-dev-server": "^3.8.1"
}
}
error:-
Webpacker can't find application in D:/Projects/Ruby
Project/helloworld/public/packs/manifest.json. Possible causes:
You want to set webpacker.yml value of compile to true for your environment
unless you are using the webpack -w or the webpack-dev-server.
webpack has not yet re-run to reflect updates.
You have misconfigured Webpacker's config/webpacker.yml file.
Your webpack configuration is not creating a manifest.
Your manifest contains:
{
}
Extracted source (around line #10):
<body>
<%= yield %>
<%= javascript_pack_tag 'application' %>
</body>
</html>

Try using Preact 10 instead of 8. preact-rails seems to be using 10 in their docs.

It can be easily done using CDN.
<h1>Render by Preact client library using h and render function</h1>
<div id="preact">
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/preact/8.5.2/preact.dev.js">
</script>
<script>
var Component = window.preact.Component,
h = window.preact.h,
render = window.preact.render;
var PreactApp = function (props){
return h('h1',
{className: ''},
'Hello world!');
}
render(PreactApp(),document.getElementById("preact"));
</script>

Related

Unable to install Tailwindcss into Rails 6

I'm currently trying to install Tailwind into a rails 6 application via Webpack but after following the docs the styles are not being applied to a view template as shown in the image. I have Tailwind v1.0.3. I also tried to upgrade Webpack to v4 so not sure if it's something due to that.
I have the following files:
javascript/css/application.css
#import "tailwindcss/base";
#import "tailwindcss/components";
#import "tailwindcss/utilities";
My packs/application.js looks as follow:
require("stylesheets/application.scss")
And my /postcss.config.js
module.exports = {
plugins: [
require('tailwindcss'),
require('autoprefixer'),
require('postcss-import'),
require('postcss-flexbugs-fixes'),
require('postcss-preset-env')({
autoprefixer: {
flexbox: 'no-2009'
},
stage: 3
})
]
}
I can also see from the packaje.json file that Tailwind was in fact installed.
{
"name": "artsy_space",
"private": true,
"dependencies": {
"#rails/webpacker": "3.5",
"tailwindcss": "^1.0.3",
"vue": "^2.5.17",
"vue-loader": "14.2.2",
"vue-template-compiler": "^2.5.17"
},
"devDependencies": {
"webpack-dev-server": "2.11.2"
}
}
and the application.html.erb
<!DOCTYPE html>
<html>
<head>
<title>ArtsySpace</title>
<%= csrf_meta_tags %>
<%= csp_meta_tag %>
<%= stylesheet_link_tag 'application', media: 'all', 'data-turbolinks-track': 'reload' %>
<%= stylesheet_pack_tag 'stylesheets', media: 'all', 'data-turbolinks-track': 'reload' %>
<%= javascript_pack_tag 'application', 'data-turbolinks-track': 'reload' %>
</head>
<body>
<p class="alert alert-error">
<%= flash[:alert] %>
</p>
<p class="alert alert-info">
<%= flash[:notice] %>
</p>
<%= yield %>
</body>
</html>
H
ere is a link to a PR in the repo.
Any idea what might it be?
It appears you might be requiring the wrong directory. Try changing:
require("stylesheets/application.scss")
to:
require("css/application.css")
Also, note that you're requiring a .scss file but it looks like the actual file is .css?
Try adding this line to your javascript/packs/application.js file
require("stylesheets/application.scss")
Everything else looks correct.
I'm also assuming you ran yarn add tailwindcss in your console.
If adding that file doesn't work, try running bin/webpack in your console.
If there are any error messages, they will help you debug the issue.
The only thing that worked for me is importing manually tailwind file into the application.js file.
require("./../../assets/stylesheets/application.tailwind.css")
and then running rails assets:clobber

React component not rendering when using react-rails gem

I followed the 'Getting started with webpacker' in react-rails but on running the rails server I dont see the hello world component there.
app/javascript/components/HelloWorld.js
import React from "react"
import PropTypes from "prop-types"
class HelloWorld extends React.Component {
render () {
return (
<React.Fragment>
Greeting: {this.props.greeting}
</React.Fragment>
);
}
}
HelloWorld.propTypes = {
greeting: PropTypes.string
};
export default HelloWorld
views/layout/application.html.erb
<!DOCTYPE html>
<html>
<head>
<title>MyApp</title>
<%= csrf_meta_tags %>
<%= csp_meta_tag %>
<%= stylesheet_link_tag 'application', media: 'all', 'data-turbolinks-track': 'reload' %>
<%= javascript_include_tag 'application', 'data-turbolinks-track': 'reload' %>
<%= javascript_pack_tag 'application' %>
</head>
<body>
<%= yield %>
</body>
</html>
views/home/index.html.erb
<!DOCTYPE html>
<html>
<body>
<p>Heloo</p>
<%= react_component("HelloWorld", { greeting: "Hello from react-rails." }) %>
</body>
</html>
app/javascript/packs/application.js
/* eslint no-console:0 */
// This file is automatically compiled by Webpack, along with any other files
// present in this directory. You're encouraged to place your actual application logic in
// a relevant structure within app/javascript and only use these pack files to reference
// that code so it'll be compiled.
//
// To reference this file, add <%= javascript_pack_tag 'application' %> to the appropriate
// layout file, like app/views/layouts/application.html.erb
// Uncomment to copy all static images under ../images to the output folder and reference
// them with the image_pack_tag helper in views (e.g <%= image_pack_tag 'rails.png' %>)
// or the `imagePath` JavaScript helper below.
//
// const images = require.context('../images', true)
// const imagePath = (name) => images(name, true)
console.log('Hello World from Webpacker')
// Support component names relative to this directory:
var componentRequireContext = require.context("components", true)
var ReactRailsUJS = require("react_ujs")
ReactRailsUJS.useContext(componentRequireContext)
This is what I get when I try to access the webpage
EDIT:
Adding prerender: true (server-side rendering) in view, it works perfectly
<%= react_component("HelloWorld", { greeting: "Hello from react-rails." }, prerender: true) %>
but why wont client side rendering work?
try adding
<%= javascript_pack_tag 'application' %>
in your index.html.erb
This issue is related to how your view is set up.
Your view is rendering a full HTML doc and ignoring the layout, therefore the JavaScript is not loaded on the page at all. This explains why everything will be undefined on the window.
In your screenshot in the question you can see the HTML HEAD is empty.
Replace the view with the following.
views/home/index.html.erb
<p>Heloo</p>
<%= react_component("HelloWorld", { greeting: "Hello from react-rails." }) %>
Also ensure that your layout file is rendering correctly by putting something visible temporarily in it. You could temporarily put the view content into the template to ensure both things at once!
Hope this helps.

Rails 5.2: Best practice for setting CSP nonce

Our application is on Rails 5.2 and it is serving assets with webpacker without the asset pipeline. I was wondering what is the best way to set the nonce attributes on the script tag.
In content_security_policy.rb, there is a content_security_policy_nonce_generator for UJS, I was wondering if I can still use that without any side effect. The following work and I was just wondering what is the best practice for doing something like this.
#initializers/content_security_policy.rb
# If you are using UJS then enable automatic nonce generation
Rails.application.config.content_security_policy_nonce_generator = -> request { SecureRandom.base64(16)
In application.html.erb, if I want to have nonce on the script tag, I will have to get it from the request. According here: https://api.rubyonrails.org/classes/ActionDispatch/ContentSecurityPolicy/Request.html#method-i-content_security_policy_nonce
#app/views/layouts/application.html.erb
<!DOCTYPE html>
<html dir="ltr">
<head>
<title>FruitsMarket</title>
<%= csrf_meta_tags %>
<%= csp_meta_tag %>
<%= stylesheet_pack_tag 'application' %>
<%= javascript_pack_tag 'polyfills' %>
<%= javascript_pack_tag 'application' %>
<script type="text/javascript" nonce=<%= request.content_security_policy_nonce %>>
alert('hi');
</script>
</head>
<body>
<%= yield %>
</body>
</html>
Found it https://api.rubyonrails.org/classes/ActionView/Helpers/JavaScriptHelper.html
turns out there is a ruby view helper for that
<%= javascript_tag nonce: true do -%>
alert('All is good')
<% end -%>

How To load js only in one page of my app

I'm trying to load a js file into a single page of my app. But it is called in all and this ends up generating errors on my screen.
My application.js is:
//= require jquery
//= require rails-ujs
//= require activestorage
//= require turbolinks
//= require_tree .
My application.html.erb
<!DOCTYPE html>
<html>
<head>
<title>Netshow</title>
<%= csrf_meta_tags %>
<%= csp_meta_tag %>
<%= stylesheet_link_tag 'application', media: 'all', 'data-turbolinks-track': 'reload' %>
<%= javascript_include_tag 'application', 'data-turbolinks-track': 'reload' %>
</head>
<body>
<div class='cover-container d-flex w-100 h-100 p-3 mx-auto flex-column'>
<header class='masthead mb-auto'>
<%= render 'shared/navbar' %>
</header>
<%= yield %>
<footer class='mastfoot mt-auto'>
<%= render 'shared/footer' %>
</footer>
</div>
</body>
</html>
My js file is:
$(document).on("turbolinks:load", function() {
console.log('teste')
var player = videojs('my_video_1');
var options = {};
player.on('play', function() {
$.ajax({
type: 'POST',
url:"/video_clicks/",
dataType: 'json',
data: {
video_click: { video_id: window.location.pathname.split('/')[2] }
},
success: function(){
$('span.video-count')[0].innerText = parseInt($('span.video-count')[0].innerText) + 1
}
});
});
function showCount(){
var id = window.location.pathname.split('/')[2]
$.ajax({
type: 'GET',
url:"/video_clicks/"+id,
dataType: 'json',
success: function(data){
console.log($('span.video-count')[0])
$('span.video-count')[0].innerText = data
}
});
}
showCount()
});
I would like to load the js file only on one page of my app and not at all. How can I do this? I have already tried removing the require_tree add content in application.html.erb and set the content in my html file, but the rails speaks that I have to add the file in assets.erb for precompilation and when I do this the other pages reload my js file.
You have multiple options in that scenario:
You can check the params[:controller] and params[:action] in application.html.erb, if that matches the specific page controller+action then only load the JS. (Better Solution)
Like:
<% if params[:controller] == 'your_controller_name' && params[:action] == 'your_action_name' %>
<%= render partial: 'shared/custom_js' %>
<% end %>
Based on this code above, I'll create a new file named custom_js.html.erb in my views > shared folder. Then write the script in that file inside <script></script> tag. Also, you need to remove that script file from application.js file.
You can create a different layout for that specific page access method. Like the answer here.
You just simply include that page (erb file) with <%= javascript_include_tag 'js_file_name' %>
Add to you view and
<%= javascript_include_tag 'js_file_name' %>
config/initializers/assets.rb
Rails.application.config.assets.precompile += %w(js_file_name.js)

Get 'Zone already loaded' error in Rails + webpack + angular 2 initial setup

I used following specifications.
1) rails 5.1.3
2) ruby 2.4.1
3) rail with webpacker
4) Angular 4.3.4 with webpacker (Typescript)
I create new rail app using command rails new my-rails-app --webpack-angular.
Folder structure
After that, as per instruction under app/javascript/packs/application.js and app/javascript/packs/hello_angular.js, I added <%= javascript_pack_tag 'application' %> in application.html.erb to head tag next after javascript_include_tag.
Also add below markup to body tag in layout application.html.erb
// <hello-angular>Loading...</hello-angular>
//
// <%= javascript_pack_tag 'hello_angular' %>
application.html.erb
<!DOCTYPE html>
<html>
<head>
<title>AngularOnRailsWithWebpack</title>
<%= csrf_meta_tags %>
<%= stylesheet_link_tag 'application', media: 'all', 'data-turbolinks-track': 'reload' %>
<%= javascript_include_tag 'application', 'data-turbolinks-track': 'reload' %>
<%= javascript_pack_tag 'application' %>
</head>
<body>
<hello-angular>Loading...</hello-angular>
<%= javascript_pack_tag 'hello_angular' %>
<%= yield %>
</body>
</html>
Now create new scaffolding by running rails g scafolld post title:string desc:text and set post index page as root path
Now run rails server by running rails s and webpack server by running ./bin/webpack-dev-server
Works fine.
But When I navigate routes by click on new post or edit post it fire errors in web console like below.
Solution I tried
1) Remove javascript_include_tag from application.html.erb. But it will remove turbolink. I don't want to remove that.
2) Restore javascript_include_tag and update index.ts under app/javascript/hello-angular/index.ts. Add turbolink load event as per this video instruction https://www.youtube.com/watch?v=lGToT9RyDxc
Index.ts
import './polyfills.ts';
import { platformBrowserDynamic } from '#angular/platform-browser-dynamic';
import { AppModule } from './app/app.module';
document.addEventListener('turbolinks:load', () => {
platformBrowserDynamic().bootstrapModule(AppModule);
})
Work fine. It will render code fine but still same zone error in web console.
May be this is rails issue. If so then I hope it will resolve in next patch release.
Can any one help that how to resolve this issue ? What I am doing wrong.

Resources