How to add jstree via webpacker to Rails - ruby-on-rails

I have a Rails 6 app where I added jstree library via yarn. I have application.js file where are the require statement. I want to do the following
$('#tree').jstree(); but this results in function jstree undefined exception. How should I require it?

Create a new Rails app:
rails new myapp
cd myapp
Install jstree and jQuery (which it depends upon):
yarn add jstree jquery
Create a new controller and view:
rails g controller welcome index
Start the dev server and the Rails server:
./bin/webpack-dev-server
rails s
In packs/application.js:
require('../../../node_modules/jstree/dist/themes/default/style.min.css');
global.$ = require('jquery');
require('jstree');
$(() => {
$('#jstree').jstree();
});
Add some HTML to welcome#index:
<div id="jstree">
<ul>
<li>Root node 1
<ul>
<li id="child_node_1">Child node 1</li>
<li>Child node 2</li>
</ul>
</li>
<li>Root node 2</li>
</ul>
</div>
Visit http://localhost:3000/welcome/index to see jstree in action.
HTH

Related

Rails + React App Pages Require Reload To Render React

I created a new Rails + React app using rails new exampleapp --webpack=react. On my home page, I have a header in html.erb, and some react jsx being rendered using <%= javascript_pack_tag 'reactfilename' %>.
When I click on a link to my home page, such as <li><%= link_to "Home", root_path %></li>, only the header is rendered. It is only till I reload the page that my react component is shown.
I am running both rails s and ./bin/webpack-dev-server to start my application. The same problem is occurring on my Heroku web server. in which I have the following setup:
Procfile:
web: bin/rails server -p $PORT -b 0.0.0.0
Procfile.dev:
web: ./bin/rails server
webpacker: ./bin/webpack-dev-server
Is this the expected behaviour of a React + Rails app, or is there a problem in my configuration?
I believe this issue has something to do with turbolinks background optimization. One workaround is to cause a complete refresh of the page by setting turbolinks to false:
<%= link_to "Home", root_path, data: { turbolinks: false } %>
With newer versions of turbolinks:
<%= link_to "Home", root_path, data: { turbo: false } %>
make sure you are loading you component after turbolink:load event
document.addEventListener('turbolinks:load', () => {
let container = document.getElementById('react-order')
if (!container) return
ReactDOM.render(
<OrderForm />,
container)
})

Angular ui-router templates are not loading, Rails backend

I'm following along with the Angular/Rails tutorial at Thinkster and I've run into an issue which seems to be most likely be Angular-related. Everything works just fine until I get to the Angular Routing section. Simply put, the inline templates within the <script> tags do not load in the <ui-view></ui-view> element. I originally thought this may be due to having opened the page locally as a file rather than having it loaded from a server, but the same problem persists even after integrating Rails (using an older version of Sprockets, as pointed out in this similar but unrelated issue).
When I load the index page in either the browser as a file or as a URL when running the Rails server, I've inspected the HTML and, sure enough, the only thing it shows in the code are the divs and an empty <ui-view> element, indicating something just isn't adding up correctly. I've tried various things, including:
Using the newest version of ui-router (0.2.15 at this writing) rather than the version in the tutorial
Using <div ui-view></div> instead of <ui-view></ui-view>
Changing the value of 'url' in the home state to 'index.html', including using the full path to the file (file:///...)
Putting the contents of the inline <script> templates into their own files (without the <script> tags, of course) and specifying the 'templateUrl' field using both relative and full paths
Trying both Chrome and Firefox just to be extra certain
None of these things have worked, even when accessing http://localhost:3000/#/home when the Rails server is running after having integrated Angular into the asset pipeline in the Integrating the Front-end with the Asset Pipeline section of the tutorial. Indeed, the route loads but does not show anything more than a completely blank page with a lonesome and empty <ui-view> element when inspecting the HTML using Chrome's dev tools.
Given that the issue seems to occur even before the Rails portion, it does seem like something to do with Angular itself, but I've got no clue what's going on, especially since I've followed along to the letter.
I'm using Bower to manage the Angular dependencies and the HTML does show that the Angular javascript files in both the app/assets/javascripts directory and in the vendor/assets/bower_components directory are being loaded properly in the <head> section, so everything seems to be okay on the asset pipeline integration.
Versios I'm using:
Rails: 4.2.3
Ruby: 2.2.1p85
Angular: 1.4.3
ui-router: 0.2.15
The code I've got for the major moving parts is below:
app/views/layouts/application.html.erb
<!DOCTYPE html>
<html>
<head>
<title>Test App</title>
<%= stylesheet_link_tag 'application', media: 'all' %>
<%= javascript_include_tag 'application' %>
<%= csrf_meta_tags %>
</head>
<body ng-app="testApp">
<div class="row">
<div class="col-md-6 col-md-offset-3">
<ui-view></ui-view>
</div>
</div>
</body>
</html>
app/assets/javascripts/app.js
angular.module('testApp', ['ui.router', 'templates']).config(['$stateProvider', '$urlRouteProvider', function($stateProvider, $urlRouteProvider) {
$stateProvider
.state('home', {
'url': '/home',
'templateUrl': 'home/_home.html',
'controller': 'MainCtrl'
})
.state('posts', {
'url': '/posts/{id}',
'templateUrl': 'posts/_posts.html',
'controller': 'PostsCtrl'
});
$urlRouteProvider.otherwise('home');
}]);
app/assets/javascripts/application.js
//= require angular
//= require angular-rails-templates
//= require angular-ui-router
//= require_tree .
app/controllers/application_controller.rb
class ApplicationController < ActionController::Base
protect_from_forgery with: :exception
respond_to :json
def angular
render 'layouts/application'
end
end
config/routes.rb
Rails.application.routes.draw do
root to: 'application#angular'
end
app/assets/javascripts/home/mainCtrl.js
angular.module('testApp').controller('MainCtrl', ['$scope', 'posts', function($scope, posts) {
$scope.posts = posts.posts;
$scope.addPost = function() {
if (!$scope.title || $scope.title === "")
return;
$scope.posts.push({
'title': $scope.title,
'link': $scope.link,
'upvotes': 0,
'comments': [
{'author': 'Some Person', 'body': 'This is a comment.', 'upvotes': 0},
{'author': 'Another Person', 'body': 'This is also a comment.', 'upvotes': 0}
]
});
$scope.title = "";
$scope.link = "";
};
$scope.incrementUpvotes = function(post) {
post.upvotes++;
};
}]);
app/assets/javascripts/posts/postsCtrl.js
angular.module('testApp').controller('PostsCtrl', ['$scope', '$stateParams', 'posts', function($scope, $stateParams, posts) {
$scope.post = posts.posts[$stateParams.id];
$scope.addComment = function() {
if($scope.body === '')
return;
$scope.post.comments.push({
'body': $scope.body,
'author': 'user',
'upvotes': 0
});
$scope.body = '';
};
}]);
app/assets/javascripts/posts/posts.js
angular.module('testApp').factory('posts', ['$http', function($http) {
var o = {
'posts': []
};
o.getAll = function() {
return $http.get('/posts.json').success(function(data) {
angular.copy(data, o.posts);
});
};
return o;
}]);
If any other code is required to help uncover the problem, please let me know and I'll supply anything requested.
it seems that the angular-ui-router is incompatible with the new Rails sprockets. To fix this, add this earlier version of sprockets to your gemfile:
gem 'sprockets', '2.12.3'
And then run bundle update sprockets.
This was answered a few times in other similar questions, like the one below:
Angular Rails Templates just not working
$urlRouteProvider in my code should've been $urlRouterProvider. Be sure to double-check everything, folks, and make good use of the console!

Rails wiked_pdf page breaks not working

I have a Rails 3.2 app using Bootstrap and Wicked_pdf. I'm trying to page break the pdf after each #costproject.
Gems:
gem 'wicked_pdf'
gem 'wkhtmltopdf-binary'
I read this post: Rails WickedPDF Page Breaks
So, I tried it.
This is in my CSS:
.page-break {
display:block;
clear:both;
page-break-after:always;
}
And this is in projects.pdf.erb:
<% #costprojects.each do |costproject| %>
<div class="page-break"></div>
<div id="pdfbody">
<table class="table table-striped">
...
But, the page breaks don't happen.
Thanks for the help!
I tried a lot of different approaches.
Placing this code in the viewprojects.pdf.erb worked for me:
<p style='page-break-after:always;'></p>

Dashing (Ruby) Nokogiri LoadError

I've been working on a dashboard on the Dashing framework, and I'm currently trying to make a little crawler to collect specific data on Jenkins-CI, and pass it to the Number widget. Here's the crawler (it's just a stub, it counts the number of "p" elements on a stub html page):
require 'nokogiri'
require 'open-uri'
class ActiveBuilds
def initialize()
#jenkins_page = nil
#build_count = nil
end
# !STUB! Gets the jenkins page to parse to XML on Nokogiri
#jenkins_page = Nokogiri::HTML(open("http://localhost:80"))
# !STUB! Counts the number of 'p' items found on the page
#build_count = #jenkins_page.css("p").length
# !STUB! Returns the amount of active builds
def amountOfActiveBuilds
return #build_count
end
end
and for reference, not really necessary, is the HTML page:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Number Stub | Project</title>
</head>
<body>
<h1>Test</h1>
<ul>
<!-- Count these -->
<li> <div> <p>Item 1 </div>
<li> <div> <p>Item 2 </div>
<li> <div> <p>Item 3 </div>
<li> <div> <p>Item 4 </div>
<li> <div> <p>Item 5 </div>
<!-- Stop counting -->
<li> <div> Item 6 </div>
<li> <div> Item 7 </div>
</ul>
</body>
</html>
and now, the jobs/sample.rb file from dashing, modified (the only thing that matters is the builds/valuation stuff):
require './ActiveBuilds.rb'
active_builds = ActiveBuilds.new
current_valuation = active_builds.amountOfActiveBuilds
current_karma = 0
SCHEDULER.every '2s' do
last_valuation = current_valuation
last_karma = current_karma
current_karma = rand(200000)
send_event('valuation', { current: current_valuation, last: last_valuation })
send_event('karma', { current: current_karma, last: last_karma })
send_event('synergy', { value: rand(100) })
end
The thing is, before I had it working, it would get the page on localhost, count the number of "p" items and print it on a file, and then the dashing file would read it and display it correctly, but it wasn't updating the value on the dashboard unless I'd restart it, which defeats the purpose of this framework.
now to the errors:
When attempting to compile sample.rb (the dashing file):
$ ruby sample.rb
sample.rb:12:in '<main>': uninitialized constant SCHEDULER (NameError)
When attempting to run the dashing server:
$ dashing start
/home/yadayada/.rvm/gems/ruby-2.2.0/gems/backports-3.6.4/lib/backports/std_lib.rb:9:in 'require': cannot load such file -- nokogiri (LoadError)
from /home/yadayada/.rvm/gems/ruby-2.2.0/gems/backports-3.6.4/lib/backports/std_lib.rb:9:in 'require_with_backports'
from /home/yadayada/Desktop/dashing/project/jobs/ActiveBuilds.rb:2:in '<top (required)>'
(...)
I could also post the HTML/CSS/CoffeScript components of the Number widget, but I believe the problem lies on the sample.rb, and the Number widget is completely default.
In case the code wasn't clear enough, what I'm trying to do is to get the localhost page, count the number of "p" items (later it'll be the active builds when I switch to jenkins, didn't switch yet because i'm dealing with the certificates), then send it over to sample.rb, which will get the data and update it every 2 seconds on the dashboard display.
Any suggestions are welcome! Thanks in advance!
Found the solution:
uninstall/reinstall nokogiri gem (without sudo)
put my crawler into the lib folder and require it inside the jobs
on the job itself, placed everything into the SCHEDULER function, like this:
# This job provides the data of the amount of active builds on Jenkins using the Number widget
# Updates every 2 seconds
SCHEDULER.every '2s' do
# Invokes the crawlers from the lib folder
Dir[File.dirname(__FILE__) + '/lib/*rb'].each { |file| require file }
# Create the ActiveBuilds reference
builds = ActiveBuilds.new
# Attributes the amount of active builds to the current valuation
current_valuation = builds.get_amount_of_active_builds
# Pass the current valuation to the last to present the change percentage on the dashboard
last_valuation = current_valuation
# Sends the values to the Number widget (widget id is valuation)
send_event('valuation', { current: current_valuation, last: last_valuation })
end

collection_select with select2 and bootstrap: undefined is not a function

In a Rails 4.1 app, I have a collection select that is loaded from a hash. I would like to use the select2 boostrap styling, but it doesn't seem to be working.
I have included the select2-rails gem, and updated application.js and application.css as per the instructions.
gem 'select2-rails'
//= require select2
*= require select2
*= require select2-bootstrap
The collection_select is loaded from a constant on the model. I don't think this is especially relevant to the issue, but added it here in case it helps someone.
FLASHCARD_TYPE = {"verb" => "Verb Conjugation",
"name" => "Word",
"number" => "Number",
"quiz" => "Quiz"}
Rails view
<div class="form-group">
<%= f.label :card_type, :class => "col-sm-2 control-label" %>
<div class="col-sm-2">
<%= f.collection_select(:card_type, Flashcard::FLASHCARD_TYPE, :first, :last) %>
</div>
</div>
app/assets/javascripts/application.js
$(document).ready(function(){
$("#flashcard_card_type").select2();
});
The rendered html shows the select2 javascript, and the select shows as:
<div class="form-group">
<label class="col-sm-2 control-label" for="flashcard_card_type">Card type</label>
<div class="col-sm-2">
<select id="flashcard_card_type" name="flashcard[card_type]">
<option value="verb">Verb Conjugation</option>
<option value="name">Word</option>
<option value="number">Number</option>
<option value="quiz">Quiz</option></select>
</div>
</div>
How can this to work properly?
In fact I would also like the option to have a site-wide default for all selects via class, then the ability to override styling by individual id.
I thought this would work as site-wide for all selects, but it also does nothing.
$(document).ready(function(){
$("select").select2();
});
EDIT
As recommended by #San I checked the Javascript console, and got
Uncaught TypeError: undefined is not a function
This the code it failed on
$(document).ready(function(){
$("#flashcard_card_type").select2();
});
EDIT 2
Full application.js file
//= require jquery
//= require jquery_ujs
//= require bootstrap-sprockets
//= require bootstrap-markdown
//= require select2
//= require_tree .
$(document).ready(function(){
$("#flashcard_card_type").select2();
});
EDIT 3
jQuery is finding the element OK
$(document).ready(function(){
debugger;
console.log($("#flashcard_card_type"))
$("#flashcard_card_type").select2();
});
log
[select#flashcard_card_type, context: document, selector: "#flashcard_card_type", jquery: "1.11.1", constructor: function, toArray: function…]
0: select#flashcard_card_type
context: document
length: 1
selector: "#flashcard_card_type"
__proto__: Object[0]
EDIT - What I have tried
removed turbolinks
added the javascript to the page
deleted cache, restarted rails
What I have found
jQuery can find the tag
The select2 library is loaded via the network tab in the js debugger
Any ideas?
Just wondering. Did you run bundle install after adding the gem to the Gemfile?
If you did, the last thing to check is to make sure select2 JavaScript file is loading before your block to use it. Verify that by doing view source on the page and make sure select2.js is listed before application.js file (assuming you are in dev mode).

Resources