(Jade or Slim)-like syntax for React? - reactjs

I've gotten used to using slim and jade and I recently moved to writing applications on the front end with React and find that now I'm writing bloated HTML again inside my components. I'm currently using Ruby on Rails and .jsx files with babel, etc using:
gem 'react-rails', '~> 1.4.0'
gem 'react-router-rails', '~>0.13.3.2'
But I'm also using React with node and express using the react-starterify boilerplate and it's the same story with Node.
Is there anything that can allow me to start writing my html in React using a syntax like slim or Jade?

One thing to keep in mind is that JSX isn't HTML—it just looks like it. This is important because the JSX transpiler (usually Babel these days) takes the JSX syntax and modifies it from this:
<div className="container">
<p>Testing!</p>
</div>
to something like this:
React.createElement("div", { className: "container" },
React.createElement("p", null, "Testing!")
)
By abstracting over React.createElement calls, you can end up with a project like r-dom, which does the same thing but with a nicer syntax:
r.div({className: 'container'}, [
r.p('Testing!'),
])
or react-hyperscript, which allows an alternative syntax for some properties:
h('div.container', [
h('p', 'Testing!')
])
However, since JSX turns into plain JS calls, any language or syntax that can be converted into React.createElement calls will work great with React, as long as you set up your Rails asset pipeline so that it correctly does the transpilation as part of serving assets.
There is a project that does this with Jade's syntax called react-jade; there are a few differences from regular Jade and some unsupported features, but it may do what you want it to do. In a Rails project, you'd need to find or create a preprocessor that turns the appropriate Jade code into React-specific JS.
There's one other thing I wanted to mention based on a comment in your question:
now I'm writing bloated HTML again inside my components
If you're just talking about HTML's syntax then no problem, but if you're finding that the render methods of your React components are getting large and hard to manage, then it's probably a good sign that you need to break your component into smaller components (see "Tip 4: Embrace composition!" at this link).

Related

Esformatter - Ignoring JSX

I am struck looking for a way to ignore JSX while using esformatter ....
esformatter-jsx-ignore wont work because of es6 imports in my project and making formatJSX = false of esformatter-jsx can't be used either as it just disables the esformatter-jsx plugin.

Separate templates to external file in React

I am working on a ReactJS app for a client. I want the client to be able to customize some of the configurations and templates in the app. So I have created a config.js file
window.APP_CONFIG = {
url: 'example.com',
template: {
item: '
<div>
<h3>A new item title</h3>
{ item.description }
</div>
'
}
};
How can I use this variable in my react app? I have tried the following but it gives me errors.
var app = React.createClass({
render(){
return (
<div>
{APP_CONFIG.template.item}
</div>
)
}
})
Anyone has done something similar?
You are not alone. React Templates allows you to use react without having to put up with inline jsx.
The react-templates syntax is very very similar to jsx but allows you to have your component html code in a separate .rt file - much cleaner. RT files have better support for looping and branching. Added bonus, you do not have to dance around reserved attribute names like "class" and "for" and there are other advantages.
From the docs:
Why not use JSX?
Some love JSX, some don't. We don't. More specifically, it seems to us
that JSX is only a good fit for components with very little HTML
inside. And this can be accomplished by creating DOM elements in code.
Also, we like to separate code and HTML because it just feels right.
The main gotcha I've seen so far is that attribute values like onMouseDown={someJsExpr} are magically quoted in jsx but in react-templates you have to explicitly quote them a la onMouseDown="{someJsExpr}", no magic. I found that it was not hard to find cases of this and convert them over.

#section syntax instead of requirejs or browserify for angularjs application

I understand that requirejs and browserify can load my files dependent on its current context, and that it is amazing. I would really prefer to use the #section sections syntax that the razor engine uses. Was just wondering if there is a way to implement this into a typescript / angularjs application.
for example
index.html
#renderSection scripts;
// which could turn into something like
<script data-render="scripts"></scripts>
// the app.run() could declare all the scripts that will be needed on every
// page view
view.html
<script ng-section-repeat="injected in injection"></script>
// the ng-section-repeat is basically taking all the items in the
// typescript constructor and then finding out which ones are needed for
// that view.
I like the idea injecting application file dependencies in the view , without a configuration file and all the added extras that comes with the loaders.
I just want to easily define what files are needed in the actual view and get them loaded, with angular's dependency injection handling the dependency itself.
If you are handling all your dependencies with $inject then , as far as i can tell, dependency is technically already setup in the controllers, all one would need, is to load this as it is called. Which could even eliminate the need for the #section scripts completely
Update:
What i have done to sort of replicate the module loaders is to just use gulp-concat and define the file order in my gulp.config.js and then pass it to the gulp-src before running $.concat .this allows me to have the files in the gulp steam , in dependent order . They are however loaded on the first load. With gulp-uglify the files are tiny ( its now at 566Kb with 16 external libraries loading in 69ms . To put that into perspective it takes 209ms to load one google font ).
I dont know maybe i am not understanding browserify correctly but i honestly struggle to see the need for it, its seems extremely convoluted for something so simple
It is possible using external modules and an injector to do what you asked for:
I just want to easily define what files are needed in the actual view
import {UserFactory} from 'models/userFactory';
import {UserValidator} from 'models/userValidator';
import {Inject} from 'angular2/di';
and get them loaded, with angular's dependency injection handling the dependency itself.
Note: My example uses angular 2.x because I less familiar with angular 1.x and I'm sure you can do something really similar...
class SomeComponent {
userName: string;
userRating: number;
rating: number;
constructor(
#Inject(UserFactory) UserFactory
#Inject(UserValidator) UserValidator
)
{
this.UserFactory = UserFactory;
this.UserValidator = UserValidator;
}
}
Then you can use Browserify to create a bundle.js file that can be executed in a web browser.

IntelliJ IDEA / Webstorm and AngularJS / Ionic

I love it when multiple technologies come together to produce a doozy...
The following AngularJS template squawks an error in the IDE ("can't resolve file"). I find the inspection wildly convenient and I don't simply want to turn it off.
/my_project/www/templates/logo.html
...
<img src="img/logo.png"/> <<< file at /my_project/www/img/logo.png
...
Question:
How can we allow an IDE like IntelliJ IDEA or WebStorm to play nice with Ionic/AngularJS/Cordova in this situation?
NOTE: I cannot simply mark the www folder as a "resources root" and use absolute references because ionic needs relative refs...
Or does it? Is there a way to fix this on the cordova side of things to allow absolute refs? i.e., so it doesn't break when deploying to Android (because we need the prefix file://android_asset/www/)
Inspired by this answer, I ended up creating a recursive search/replace script in the build process. I made a cordova hook for "after_prepare" and used node with the replace package. Now I can use absolute refs and get the full benefit of the IDE... and then at build-time they get converted to relative.
Here is a sample hook file to get you started. Don't forget to add refs for css files or things like templateUrl in your app.js if you're using angular/ionic. And of course don't forget to modify the platform specifics to your needs.
#!/usr/bin/env node
var replace = require("replace");
var wwwDir = process.argv[2] + '\\platforms\\android\\assets\\www';
// convert all src and href tags to relative in index.html + components\*
replace({
regex: '(src|href)=([\'"])/+',
replacement: '$1=$2',
paths: [
wwwDir + '\\components',
wwwDir + '\\index.html'
],
recursive: true,
silent: false
});

Using Moovweb only some of the inline styles are being removed

So I am working in a very old site that is table heavy - everything has been converted to divs, and inside of main.ts I have tried removing the inline styles because the function remove_all_styles() is not working.
#func XMLNode.remove_all_styles() {
remove(".//link[#rel='stylesheet'][not(#data-mw-keep)]|.//style")
}
I also tried adding remove(".//#style") and still failing to remove the div style="" on half of the page. I am not having much luck finding a solution so any help would be appreciated.
edit - as a temporary solution I used this custom JavaScript I found on CSS tricks -
http://css-tricks.com/snippets/javascript/remove-inline-styles/
but I know there is a more appropriate Moovweb solution out there somewhere.
Thanks,
My guess is if you view the source, the inline styles won't be there, which means the styles are added later with JS. Otherwise remove(".//#style") would have worked if you've scoped into the right div.
The only tritium implementation that I can think of is a bit hacky but worked for me on several occasions. You need to reverse engineer the desktop js that adds those inline styles and figure out the selector it uses. Then you can find a workaround by changing the attribute or renaming the node
For example, if the desktop js is something like this
$(".price-table th").css("color", "red");
or like this $(".my-table th").attr("style", "");
You can override the class name in tritium to break the jquery selectors above.
$(".//table[#class='price-table']") {
attributes(class: "new-price-table)
}

Resources