I have been investigating the inline styles & templates vs externals in the new Angular 2 components.
I was wondering what is the recommended route. I know it doesn't matter as far as functionality is concerned.
Having styles and templates together in the component reminds me of how reactjs tackles things. It does have its advantages.
Code Completion etc? Is this better for inline vs external? I am unsure which route to take or which is recommended.
I think it's about encapsulation and uniqueness of the component. Sometime you run into situation where certain elements require some special styles. With the traditional css, you would create a unique class, sometimes use !important to make sure it applies....
with ng components, your component can share global style and at the same time have it's own unique styles. Furthermore, component's styles can be contain within itself and/or share globally, given you more flexibility to do what you want.
https://egghead.io/lessons/angular-2-controlling-how-styles-are-shared-with-view-encapsulation?series=angular-2-fundamentals
From https://angular.io/styleguide
Extract Template and Styles to Their Own Files
Style 05-04
Do extract templates and styles into a separate file, when more than 3
lines.
Do name the template file [component-name].component.html, where
[component-name] is our component name.
Do name the style file [component-name].component.css, where
[component-name] is our component name.
Why? Syntax hints for inline templates in (.js and .ts) code files are
not supported by some editors.
Why? A component file's logic is easier to read when not mixed with
inline template and styles.
Related
Cypress and many other posts around testing web applications suggest relying on a data attribute like data-cy or data-test-id for locating elements rather than relying on the id attribute.
My understanding is that for two reasons:
The modern way of re-using the components can lead to having multiple components of the same type and can lead to multiple of those IDs on the same page - But this should also apply to the 'data-cy' or 'data-test-id' attributes.
When IDs are tied to CSS, there's a tendency to change them more often while data-* attributes may be less prone to change.
Can someone please throw more light on the recommendation?
The other thing I am considering is to request my devs to place the data-test* attributes on a div tag that would consume the component - that way the test attribute is actually one level above the component id attribute and may come handy even in cases where multiple instances of the same component are used. But again, I am not sure why the id attribute for that div tag is bad when compared to the data-test* attribute.
From Cypress official docs:
Anti-Pattern: Using highly brittle selectors that are subject to change.
Best Practice: Use data-* attributes to provide context to your selectors and isolate them from CSS or JS changes.
Every test you write will include selectors for elements. To save yourself a lot of headaches, you should write selectors that are resilient to changes.
Oftentimes we see users run into problems targeting their elements because:
Your application may use dynamic classes or ID's that change
Your selectors break from development changes to CSS styles or JS behavior
Luckily, it is possible to avoid both of these problems.
Don't target elements based on CSS attributes such as: id, class, tag
Don't target elements that may change their textContent
Add data-* attributes to make it easier to target elements
The point is that id's and classes can be dynamic (also text-content) so you always want to use a selector that is static like the "data-cy" attribute.
When you have a big application which have hundreds components, some of it is heavily shared by others, and some of it just a layout or a simple view.
So is there any good advises for organizing components? by module? or by usage? or some other policies?
I create a directory per page, then stick to one component per file (ie AddButton would be in add_button.js.jsx). I always have the top-level component for that page suffixed with App.
user
user_list.js.jsx
user_app.js.jsx
dashboard
dashboard_app.js.jsx
histogram.js.jsx
analytics
shared
buttons
add_button.js.jsx
reset_button.js.jsx
list.js.jsx
table.js.jsx
This has become my default go-to approach for a while now, curious to see how others proceed.
Personally, I prefer to keep single-use components groups together in the same file. While more components is good, more files can lead to harder debugging, as you have to constantly jump between them. My folder structures often look like this:
Views
User
show.js (single view that includes view-specific components and references shared components)
index.js
Widgets
_form.js (reused only within context of widgets)
new.js
edit.js
Components (reused multiple places on the site)
List.js
ListItem.js
Navbar.js
Footer.js
You may want to consider following File System Organization pattern suggested by BEM.
A component-based approach used in the BEM methodology also determines
the way that BEM projects are organized in a file system. In BEM, it's
not just the interface that is divided into independent components,
i.e. blocks, but the implementation of blocks is also divided into
independent parts, namely files.
If you are not familiar with BEM, here is a concise introduction :
BEM – meaning block, element, modifier – is a front-end naming
methodology thought up by the guys at Yandex. It is a smart way of
naming your CSS classes to give them more transparency and meaning to
other developers. They are far more strict and informative, which
makes the BEM naming convention ideal for teams of developers on
larger projects that might last a while.
Your Vue/React components can map one-on-one to BEM blocks which are kept in individual folders containing JS implementation, CSS styles and relevant templates.
blocks/
input/
input.css # `input` block implementation in CSS technology
input.js # `input` block implementation in JavaScript technology
button/
button.css
button.js
button.png
As your project becomes more complex, it may be benefical to store Modifiers and elements are in separate files and are group into accordingly named block subdirectories
blocks/
input/
_type/ # `type` modifier directory
input_type_search.css # Implementation of modifier `type` with value `search` in CSS technology
__box/ # `box` element directory
input__box.css
input.css
input.js
button/
button.css
button.js
button.png
Are there any simple ways to patch React to autoprefix styles, such that the rendered HTML doesn't differ on the client and server?
For example, is it possible to get
<div style={{display: 'flex'}}/>
to render to (ignoring data-reactid):
<div style="display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;"/>
In the specific case you posted, you may have to make a function in which you pass your style and it creates the correct styles. In cases where a simple prefix will work, you could use something like react-prefixr which just adds ms,Webkit,etc. to the style structure. If display:flex is not handled properly by react-prefixr, you can probably submit it as PR.
I've had the same issue and wanted an easy way to mixin styles. So I created a library that lets you use less/sass style mixins https://seogrady.github.io/style-mixin.
I've just today created a simple prefixing tool, react-prefixer. This handles prefixing possibilities for relevant browsers.
I say relevant because you call out display:-webkit-box syntax, which is basically Safari 5.1, its pretty non-existent these days. Additionally, it only adds the syntax needed, meaning you won't see the full string of styles as you showed ... based on browser support, it will either provide the prefixed version or the spec version, no need to clog up the markup with useless styles.
It's still pretty young (I coded it this morning), but maybe it can help.
Is RactiveJS compatible with JSX?
I'm guessing some of the mark-up is not compatible. I like the thought of strong typing and being able to cleanly write the templates in JavaScript source. Maybe this is considered bad design?
No. React.js and Ractive.js have many similarities (for example, both work by constructing a lightweight virtual DOM in memory), but they have one very major difference - React completely rejects the idea of templates.
Which is to say that JSX isn't a templating language, it just looks like one! In React, if you have something like this...
<h1>Hello world!</h1>
...it gets converted to something like this by the JSX pre-processor:
React.DOM.h1(null, 'Hello world!');
In other words JSX describes functions, rather than templates. In Ractive, by contrast, Mustache templates are parsed into tree-like structures that can be transported as JSON.
Now, in the case of that example it doesn't really matter what process the original string goes through - it's still going to end up as an <h1> element in a browser somewhere. But it gets a lot harder when you start introducing arbitrary JavaScript which refers to this.state and this.props - things that can alter the fundamental structure of a component in React, but which have no meaning in Ractive.
Ractive might support templating languages other than Mustache in future, but JSX is unlikely to be one of them because they have such different approaches and design goals.
However there's a related issue here, which is being able to fully describe components in a single file. There's some ongoing work happening there - the most likely scenario is that we'll be able to describe components in an .html file (since you can use JavaScript and CSS inside HTML) rather than writing the template into your .js file.
I have a rather large template.php file and was looking at a better way to organise it. The main culprit is theme_preprocess_node() which has lots of code.
Can someone suggest a good way to keep this tidy and readable? Can I create custom functions in template.php.
Alternatively can this be split up into custom modules? And if so how can I get access to the $vars or $variables (page variables) that I need?
Thanks
I also faced this kind of code mess up in theme esp in template.php. My Idea Goes like this,
Collect code that helps in theming with a configuration
Create a module for the same. example collect code that helps you in theming a form and make a module.
If template.php is so large, separate out the theme override functions in to separate .inc file and include in template.php
Ex: theme related to layout or blocks as blocks_theme.inc
Alternatively can this be split up into custom modules? And if so how can I get access to the $vars or $variables (page variables) that I need?
The module you design need to serve the purpose of theming. $vars should not be passed as such. But instead try to pass the required variables to the functions and get the themed output.