Javascript

desarrollo - Javascript - React

From React Components to React Native

Many times, as developers we are working on a React website and suddenly the clients ask for a mobile version of the same App, thats when React Native comes in hand, sure you can use almost all the logic behind it, but it becomes a trouble when every html component crashes our app and we have to think about the mobile equivalent of every single Html tag, and of course it never looks the same way.

Thats where we need some other tools, in this POST ill speak about how to make that migration easier with 2 different tools, styled-components and native-base.

Getting Started

First lets create our 2 different projects. One in React-Native and one for React. For both well follow the tutorial offered in both websites.

React goes at it follows

npm install -g create-react-app
create-react-app webapp

cd webapp
npm start

and Native

npm install -g react-native-cli
react-native init NativeApp

cd NativeApp
react-native run-ios

That left us with the both default views. For React in (src/App.js) we got

<div className="App">
  <div className="App-header">
    <img src={logo} className="App-logo" alt="logo" />
    <h2>Welcome to React</h2>
  </div>
  <p className="App-intro">
    To get started, edit <code>src/App.js and save to reload.
  </p>
</div>
</code>

and in Native (index.ios.js)

<View style={styles.container}>
  <Text style={styles.welcome}>
    Welcome to React Native!
  </Text>
  <Text style={styles.instructions}>
    To get started, edit index.ios.js
  </Text>
  <Text style={styles.instructions}>
    Press Cmd+R to reload,{'n'}
    Cmd+D or shake for dev menu
  </Text>
</View>

Now lets add a List a Button and a simple Input to make it more complete. (and delete image tag)

<div className="App">
  <div className="App-header">
    <h2>Welcome to React</h2>
  </div>
  <p className="App-intro">
    To get started, edit <code>src/App.js and save to reload.
  </p>



*    First elem 

*    Second Elem 



<input name="vehicle" value="Bike" />

</div>
</code>

Great, now the thing is how to send exactly this, into a native component, if we paste this directly into our native app we get the following error: Expected a component class, got [object Object] Basically it is caused because it was expecting a native tag and we sent it an HTML tag. So we need to find an alternative route, the usual way is to think whats the equivalent tag for every HTML, change it, and then alter all the CSS so it gets a nice behavior, but thats not easy all the time, as the view gets more complicated, getting its native equivalent gets more tricky.

One way of doing this is with Styled-Components.

Styled-Components

The idea behind styled-component is to separate class looks with its functionality, with this in mind we can create an interface to every HTML tag so we can render them in a native environment, to do this we have to be familiarized with the Natives tags, and create our own. First lets install Styled-Components.

npm install --save styled-components

And then import them in our view

import styled from 'styled-components/native';

So as we got it so far, we need to create a new component for each HTML tag, so we got DIV, UL-LI, P, Input and H2. For every single one of them well create a new const like this.

const DIV     = styled.View``;
const P       = styled.Text``;
const CODE    = styled.Text``;
const H2      = styled.Text``;
const INPUT   = styled.TextInput``;
const BR      = styled.View``;
const UL      = styled.View``;
const LI      = styled.Text``;

and change our index code to this, altering all HTML tags to our new ones. I know that many of you will cry when they see that UL is a type of View and LI a type of text, the logic behind it is that ul in HTML is a sort of cotainer of all li elements that have the actual text, so we can see it as a div with paragraph inside.

<DIV className="App">
  <DIV className="App-header">
    <H2>Welcome to React</H2>
  </DIV>
  <P className="App-intro">
    To get started, edit <CODE>src/App.js and save to reload.
  </P>



*    First elem 

*    Second Elem 



<INPUT name="vehicle" value="Bike" />

</DIV>
</code>

And there we go, no more errors and it goes nicely, many would say that its the same as changing it manually, but this way you can define the regular behaviour of each element in a single component and then share it through all the views, for example, changing the H2 element to be more accurate to a headline tag in HTML, and adding a few CSS we get the regular HTML behaviour.

const DIV     = styled.View`
  padding: 10px
`;
const P       = styled.Text``;
const CODE    = styled.Text`
  font-family: 'Helvetica';
`;
const H2      = styled.Text`
  font-weight: bold;
  font-size: 20;
`;
const INPUT   = styled.TextInput`
  border: 1px solid black;
`;
const BR      = styled.View``;
const UL      = styled.View`
  padding: 20px
`;
const LI      = styled.Text``;

we get a more appealing design that can be used through all our views with no mayor interaction than changing a few tags. Please note that this doesn’t change the functionality of your app in any way, you can get even a further customization by studying styled-components.

NativeBase

NativeBase is a component library, made to create native apps quickly with very little changes to components themselves. Even thought you would still have to learn each component and see your way through replacing your HTML with nativeBase.

A plus side is that it comes with components such as sidebars, navbars, menus etc that makes your development easier.

First lets install it

npm install native-base --save
react-native link

After we make our install, we need to import the components that we will use in this view.

import { Container, Title, List, ListItem, Input, Text } from 'native-base';

Then change every tag in our index as it follows

<Container className="App">
  <Container className="App-header">
    <Title>Welcome to React</Title>
  </Container>
  <Text className="App-intro">
    To get started, edit <Text>src/App.js</Text> and save to reload.
  </Text>
  <List>
    <ListItem> First elem </ListItem>
    <ListItem> Second Elem </ListItem>
  </List>
  <Input name="vehicle" value="Bike"/>
</Container>

If you run this, you will still get an error, the famous Raw Text, this errors happens when you got a Text outside any tag and Native doesn’t know what to do about it, in our case is the text inside ListItem, ListItem its still a View type container, that means that it isn’t a component that would render a text, to change that we got to use a

<Container className="App">
  <Container className="App-header">
    <Title>Welcome to React</Title>
  </Container>
  <Text className="App-intro">
    To get started, edit <Text>src/App.js</Text> and save to reload.
  </Text>
  <List>
    <ListItem>
      <Text>First elem</Text>
    </ListItem>
    <ListItem>
      <Text>Second Elem</Text>
    </ListItem>
  </List>
  <Input name="vehicle" value="Bike"/>
</Container>

And there we go, we got a more mobile version of what we got before.

Conclusion

NativeBase gives us a template to work with, several components and premade functionalities that can lend us a hand in several applications, things such as NavBars, Forms, MenuBars, etc that already comes with a more mobile style. In the other hand styled-components gives us the ability to even import easily the css that we made already for our web components, so if we got a solid and responsive design for our web we may come in use of that level of customization.

Both of them works perfectly with each other so you can have the good sides of each one, using the more template design that provides nativeBase and a more customizable one that comes with styled-components.

Read More
angular - Javascript

Have you ever wonder how to make an Angular Application that you could lazy load the hell out of, but that also allows you to use the lazy loaded modules right after loading for, let’s say… searching?

We at CODDDE had this problem and I was tasked with solving it. As I was doing my research, I found that there weren’t many articles or examples of this, so I will share my experience, and the code behind it with a simple example.

The first thing we need to do is create the 3 modules: MainApplication, App1 and App2. The latter 2 will be lazy loaded.

Step 0

First we need to generate a main application module that will load the other modules. We can do this by creating an application with ng new my-app.

After that, navigate to /src/app and create a layout with ng generate component outer-layout that will hold our router-outlet, then open outer-layout.component.html and change the content to this:

https://gist.githubusercontent.com/sikolio/9611dfd74b679c3825dc8e77da1c2727/raw/036c4a7ecc3fa335d891daf120ffaac8acf6dfe8/outer-layout.component.html

As you see in that snippet, I will be using observables to hold our interactive data. So, let’s create the component logic in outer-layout.component.ts:

searchResults: Observable<any>;
queryString: BehaviorSubject<string>;

constructor(private service: MyService) { }

ngOnInit() {
this.searchResults = this.service.searchResults;
this.queryString = new BehaviorSubject<string>(”);
this.queryString
.debounceTime(400)
.subscribe((query) => {
this.service.search(query);
});
}

changeQuery(query) {
this.queryString.next(query);
}

Here I am injecting MyService to the component. This service will be responsible for the communication between all the modules, so we need to create it, but we want it in a shared module, since we want to be able to use it everywhere. So, let’s create our shared module with ng g m shared and then create the service inside it ng g s shared/service/myService (this is because we want the service to be inside the shared folder and inside its own folder, and the angular cli generates services on the current folder).

Open /shared/service/myService and add the following code:

searchQuery: BehaviorSubject<string>;
searchResults: BehaviorSubject<any>;

constructor() {
console.log(‘Shared Service created’);
this.searchResults = new BehaviorSubject<any>({});
this.searchQuery = new BehaviorSubject<string>(”);
}

updateSearch(from, data) {
const newData = this.searchResults.getValue();
newData[from] = data;
this.searchResults.next(newData);
}

search(query) {
console.log(‘Searching for ‘, query);
this.searchQuery.next(query);
}

Here we create two BehaviorSubject that are both an observer and an observable. Also when you subscribe to them, they return the last value emitted by them. This is perfect for our use case, as we want anyone who subscribe to both of them to immediately know the current search query.

Now it is time to provide our service, we will do this in the SharedModule as I explained early. To do this open shared/shared.module.ts and add the following code:

@NgModule({
imports: [
CommonModule
],
declarations: []
})
export class SharedModule {
static forRoot(): ModuleWithProviders {
return {
ngModule: SharedModule,
providers: [
MyService
]
};
}
}

We need the forRoot() method here to prevent the creation of multiple instances of our service that Angular defaults to.

Lastly, we need to import this module in app.module.ts of the main application, so open it and add the SharedModule.forRoot() to the imports array. ## Step 1

Next we need to create the lazy loaded modules, ng g m app-one ng g m app-two (I created 2 for this article, you can have as many as you want). Create an app.routes.ts inside each of those and add the following:

const routes: Routes = [
{ path: ”, redirectTo: ‘home’, pathMatch: ‘full’},
{ path: ‘home’, component: HomeComponent },
{ path: ‘view1’, component: ViewOneComponent },
{ path: ‘view2’, component: ViewTwoComponent },
];

export const routingModule: ModuleWithProviders = RouterModule.forChild(routes);

I won’t go over the creation of those Presentational Components, as they can be whatever you want (you can copy them from the repo if you want).

Then we need to add the SharedModule to the imports of each of these modules. To do this, add SharedModule to the imports array (notice that we aren’t adding the .forRoot())

We alse need to create a service in these apps that will be in charge of updating the shared service. To create them do ng g s app-one/services/AppOne and insert the following code in them:

subscription: Subscription;
searchableItems: BehaviorSubject<any>;

constructor(private shared: MyService, private http: Http) {
console.log(‘App One Service created’);
this.subscription = Observable.combineLatest(
this.getItems(),
this.shared.searchQuery$
)
.subscribe((data) => {
this.search(data[0].filter((item) => {
return item.toLowerCase().includes(data[1]);
}));
});
}

getItems() {
return this.http.get(‘/assets/items.json’)
.map(res => res.json());
}

search(data) {
console.log(‘appone search’, data);
this.shared.updateSearch(‘appone’, data);
}

Here I am logging to the console when the instance is created and when we search.

Finally, we need to add the AppOneService to the Providers array of each of the AppModules.

Step 2 (or “where the magic happens”)

Let’s create a file called app.routes.ts where you will define the routes of the main application (it will also determine which modules will be lazy loaded). There you should add the following routes:

const routes: Routes = [
{ path: ”, component: OuterLayoutComponent,
children: [
{ path: ”, redirectTo: ‘home’, pathMatch: ‘full’},
{ path: ‘home’, component: HomeComponent},
{ path: ‘appone’, loadChildren: ‘app/app-one/app-one.module#AppOneModule’ },
{ path: ‘apptwo’, loadChildren: ‘app/app-two/app-two.module#AppTwoModule’ },
]
},
];

Here we are redirecting the empty route to the home route, and we are adding a route for each of the applications using the loadChildren parameter of the routes. This lets us lazy load the application and also tells angular how to bundle our app.

After this you should import the RouterModule.forRoot(routes) and export it in a new Module AppRoutingModule.

Ok, so let’s see what happens if we try to run this. Try running ng serve. You should see something like the following

images before adding the lazy loader service

images before adding the lazy loader service

As you can see there, we are still missing the functionality we were seeking. In order to make this work, we have to do two things.

  1. Add the PreloadAllModules strategy to the main router module.
  2. Eager load the services of the lazy loaded modules. This is to avoid needing navigation to a page from that modules for the service to be created.

So, the first thing we need to do is add the preloadingStrategy to the options of the RouterModule.forRoot() method:

@NgModule({
imports: [RouterModule.forRoot(routes, { preloadingStrategy: PreloadAllModules })],
exports: [RouterModule],
providers: []
})
export class AppRoutingModule {}

The second thing you need to do is npm install angular-eager-provider-loader. This will let you load the services without the need to have the user navigate to any route. In order for this to work you need to add the following to each one of the lazy loaded modules:

import { EAGER_PROVIDER, EagerProviderLoaderModule } from ‘angular-eager-provider-loader’;

imports: [
…,
EagerProviderLoaderModule
],

providers: [
{ provide: EAGER_PROVIDER, useValue: AppTwoService, multi: true }
]

And there you have it, the application with lazy loaded modules that updates the searchable upon upload.

Read More
d3js - Javascript - jslib - Programación

Ejecutar Javascript en la GPU

Librería javascript para ejecutar código en la GPU. Muy útil para visualizaciones de datos:

 

https://turbo.github.io/

Read More
Javascript - jslib - Programación - Ruby

Librería javascript cuando turbolinks no puede utilizarse

Un proyecto realmente interesante para acelerar cualquier página:

https://github.com/Easyfood/pageAccelerator

 

PageAccelerator es al javascript lo que turbolinks y pajx es a ruby on rails. Impresionante experiencia de usuario.

 

 

Read More
d3js - Inspiration - Javascript

D3js – brushable horizontal rowchart

Muy buen ejemplo de brushable rowchart. Para encajar el rowchart cuando el espacio es limitado.

http://bl.ocks.org/nbremer/d8dff2fa37345d54f9e58eb74db460d0

 

Read More
Javascript - Programación - Rails

Generación dinámica de formularios

Nos han contratado par aun proyecto donde lo importante es el rellenado de un flujo de formularios. Este flujo inicialmente sencillo se ha vuelto mucho más complejo debido a que la aplicación maneja más de 50 formularios. Por ello buscamos una forma de simplificar la arquitectura de información y lo que hemos decidido hacer es utilizar un form builder. La duda a continuación es que tecnología utilizar para este form builder. Tenemos dos alternativas:

  • utilizar la gema de ruby  Rapidfire: https://rapidfire.herokuapp.com/rapidfire/
  • Utilizar un form builder JS y almacenar la info como JSON.

con la primera opción no es necesario q utilicemos postgreSQL sin embargo con la segunda opción si que es necesario cuando queremos almacenar el form y sus repuestas. Avanzaremos con el problema.

Read More
Javascript - Rails - Ruby

Formularios con campo de firma

Una gema para Rails donde se crea un wrapper para el formulario de Ruby que permite incrustar una firma.

A Rails gem for custom signature form fields
https://github.com/Brantron/john_hancock
5 forks.
85 stars.
4 open issues.
Recent commits:

Read More
Javascript

Librería javascript para reconocer gestos

Especialmente útil para el trabajo de gráficos en web móvil.

 

https://zingchart.github.io/zingtouch/

Read More
Javascript - Programación

Librería de animación javascript

Muy buena librería de animaciones en javascript

http://anime-js.com/

Read More