Angular/ AngularJS/ Javascript

Angular 2.0 mudança drástica e a Ng-conf 2015

angular2-logo

Embora o AngularJS 1.3.x e 1.4.x continue sendo mantido, a idéia é que você mude como cria apps com o novo framework 2.0.

Hoje é o segundo dia da Ng-Conf, embora seja o segundo dia, não consegui manter o ritmo em assistir as novidades vs os atributos diários, hoje como é uma sexta-feira eu consigo assitir algumas palestras.

Para quem quiser assistir as de hoje. Só assistir abaixo.

Os videos do que aconteceu ontem, podem ser acessados daqui.

Em resumo, quem perdeu ontem e quer acompanhar, basta entrar no novo site do Angular.

 www.angular.io 

Resumindo o que aconteceu ontem:

  • AngularJS agora é Angular
  • Angular agora é baseado no TypeScript
  • Angular agora é mantido pela Microsoft e Google
  • Templates muito mais simplificados
  • Controllers agora são Assincronos
  • Lazyload de Controllers por padrão
  • Mudança absurda na sintaxe
  • Suporte a E5, E6

Prometo escrever um post muito mais completo assim que consegui assitir tudo e me atualizar.

AngularJS/ Bower/ HTML5 / CSS3/ Javascript

Gravação do hangout criando Web Apps com AngularJS

angular-hangout

Agradeço aos mais de 167 participantes de assistiram ao vivo o Hangout e aos mais de 760 que já assistiram a gravação até o momento da escrita desse post.

Quem perdeu, pode assistir no youtube a gravação.

Mesmo com uma forte gripe que me arrastou para uma bronquite aguda, consegui explicar em um estilo de aula, como você pode se tornar produtivo com o AngularJS, assim como, usando o Bower, Yeoman e Grunt para automatizar as tarefas.

AngularJS/ HTML5 / CSS3/ Javascript

Convite para participar do Hangout Web Apps com AngularJS

angular-hangout

Chegou a hora de compartilhar o que aprendi nos últimos 12 meses.

Convido todos vocês leitores a aprender um pouco sobre como criar Web Apps com AngularJS nesse Hangout on-line e grátis.

Será no próximo sábado as 09:30 da manhã horário de Brasilia, e com uma duração máxima de 3 horas.

Nesse hangout como é de costume, vou comentar sobre as semelhanças do Flex com o Angular, arquitetura de uma Web App e consumindo serviços REST de forma mais fácil.

A transmissão também será gravada e disponibilizada no Youtube.

AngularJS/ Javascript

AngularJS extensões para Chrome e Firefox

angular_header

Duas extensões que fazem uma tremenda diferença para quem desenvolve para Web com algum editor simples como o SublimeText ou Atom.

Batarang para o Chrome

batarang

Angscope para Firefox

ngscope

Se você usa uma IDE mais completa como o WebStorm, você pode instalar um plugin para o Chrome do JetBrains e debugar direto.

Independente de IDE, uma boa ferramenta para explorar o scope de cada controller e diretiva é definitivamente melhor que usar o console.log(); para debugar suas próximas aplicações.

AngularJS/ HTML5 / CSS3/ Javascript

Angular 1.2.x One-Way data-binding

angular_header

A grande vantagem do AngularJS é o two-way data-binding. Embora isso seja uma excelente função, em excesso acaba causando problemas, dentre eles performance para renderizar valores.

E isso impacta diretamente na questão de Grids de dados, internacionalização, gráficos e por ai adiante.

Boa parte de aplicações usa apenas one-way data-binding, já que é parte pertinente só renderizar dados, quando se exige um certo nível de aceitação para intergir, consumir um websocket ou atualizações constantes o two-way é a solução perfeita para isso.

A atual versão do angular 1.2.24 só possui suporte ao two-way data-binding. Qual a solução para o problema? Criar uma diretiva que permita o uso apenas de uma maneira.

Entendendo o problema

Sempre que você assina o two-way com {{ }} em suas views de HTML, o angular cria uma raiz de eventos para observar se o valor vai mudar ou não, consequentemente atualizar a view.

 
     <p>Olá {{USER_NAME}}</p>

O $watch faz esse papel, criando isso em pequenas aplicações é até aceitável, já que o nível de controle é sustentável e não existe tantas variáveis sendo mudada.

Criando a diretiva One-way

var app = angular.module("OneWayApp",[]);
 
app.directive('oneWay', function() {
    return {
        scope: true,
        link: function($scope,$elm) {
            setTimeout(function() {
                $scope.$destroy();
                $elm.removeClass('ng-binding ng-scope');
            }, 0);
        }
    }
});

O que eu faço é só destruir o $watcher depois que o valor for renderizado na view, assim evito ficar olhando por mudanças que não são necessárias.

Veja um exemplo sendo executado abaixo.

One-way App

Performaticamente falando, consigo renderizar 10 mil itens na tela sem precisa olhar todos eles, tire o atributo one-way e seu Brower pode quebrar e fechar. Até a barra de rolagem fica mais suave com tantos itens sem precisa observar suas mudanças.Igor Costa

Futuro do Angular JS

Essa função vai vim built-in na próxima versão do AngularJS 1.3.

Sua anotação será da seguinte forma:

 
<p>{{::user.name}}</p>

Colocando só os ::, essa função quem quiser se arriscar na RC-1, pode usar em seus projetos futuros, embora quem ainda dependa muito de funções especificas do 1.2.x, pode usar essa diretiva.

AngularJS/ Bower/ HTML5 / CSS3/ Javascript

A quebra do build automático e o Bower no meio do caminho

bower_header

Quem usa algum esquema de integração contínua como o Jenkins por exemplo, sabe que é horrível ter a foto do Chuck Norris e saber que foi você quem quebrou o build.

O Bower geralmente é o culpado, acontece isso sempre e tem acontecido comigo nos últimos 9 builds gerados em um dos softwares que estamos fazendo.

Qual a principal causa disso?

Bom, acontece quando nós usamos diversas bibliotecas, componentes de terceiros e vem com diferentes versões do software principal que você está usando, por exemplo: Angular, JQuery e faz o Jenkins quebrar, já que o bower fica sem saber qual versão instalar.

+ bower install --silent
bower                        ECONFLICT Unable to find suitable version for angular
Build step 'Execute shell' marked build as failure
Finished: FAILURE

Mesmo eu tentando colocar via –silent, ele ignora e continua quebrando o build.

Entendendo o caso:

O Bower tem uma configuração para lá de prática e acabei descobrindo isso na quebra do build, ele possui uma conversão chamada “resolutions”, onde força você à usar a versão que você realmente quer.

{
  "name": "Seu Produto",
  "version": "0.0.1",
  "dependencies": {
    "angular": "1.2.16",
    "json3": "~3.2.6",
    "es5-shim": "~2.1.0",
    "jquery": "~2.1.1",
    "jQuery-Mask-Plugin": "1.6.4",
    "jquery-ui": "~1.10.4",
    "bootstrap": "~3.1.1",
    "angular-resource": "1.2.16",
    "angular-cookies": "1.2.16",
    "angular-sanitize": "1.2.16",
    "angular-route": "1.2.16",
    "angular-animate": "~1.2.16",
    "angular-collection": "~0.5.0",
    "angular-bootstrap": "0.11.0",
    "angular-strap": "~2.0.2",
    "momentjs": "~2.6.0",
    "ng-grid": "~2.0.11",
    "textAngular": "~1.2.1",
    "fontawesome": "~4.1.0",
    "angular-ui-utils": "~0.1.1",
    "cpf_cnpj": "~0.0.3",
    "angular-intro.js": "~1.1.2"
  },
  "devDependencies": {
    "angular-mocks": "1.2.16",
    "angular-scenario": "1.2.16",
    "angular-ui-utils": "~0.1.1",
    "jquery-ui": "~1.10.4"
  },
  "resolutions":{ "angular": "1.2.16" }
}

O “resolutions” acaba configurando implicitamente a versão do software que você quer e isso por final evita a quebra do build e o Chuck no telão na sala de desenvolvimento.

AngularJS/ Javascript

AngularJS e filtros Brasileiros

angular_header

Acabei de publicar no github um projeto bem simples e ao mesmo tempo bastante comum a tal da formatação de certos campos como, cnpj,cpf, cep e por ai vai no ramo Brasileiro.

Querendo ou não você vai encontrar esse pequeno problema no ramo uma vez ou outra na vida.

Como eu precisei e não achei nada no mercado, acabei fazendo os meus e para ninguém mais sofrer com esse problema, é só usar esses filtros.

Como usá-lo?

Instalando via bower

$ bower install ng-filters-br

Depois de executar só colocar dentro dos módulos de sua aplicação:

var app = angular.module('myApp', ['ngSanitize','brasil.filters']);

Aplicando o filtro de formatação quando necessário

É só colocar:

{{value | nome do filtro}}

Exemplo abaixo:

    <h3>Filtros valores reais brasileiros</h3>
    <p ng-repeat="value in moedas">{{value | realbrasileiro}}</p>
    <h3>Filtros para CPF</h3>
    <p ng-repeat="value in cpfs">{{value |cpf}}</p>
    <h3>Filtros para CNPJ</h3>
    <p ng-repeat="value in cnpjs">{{value |cnpj}}</p>
    <h3>Filtros para CEP</h3>
    <p ng-repeat="value in ceps_br">{{value |cep}}</p>
    <h3>Filtros para Telefones SP</h3>
    <p ng-repeat="value in tels_sp">{{value |telefone_sp}}</p>

Quem não estiver usando o Bower

Para utilizar sem o bower, basta copiar os arquivos na basta dist, seja minificado ou normal. Vai de sua escolha.

Sugestões, reclamações. Só fazer um fork, criar pull-requests ou abrir uma issue caso você não consiga fazer um pull-request.

AngularJS/ Javascript

Usando o Google Charts com AngularJS

angular_header

Se você já tentou usar o Google Charts junto com uma aplicação Angular, você acaba de esbarrar no primeiro problema relacionado à compatibilidade do AngularJS.

Geralmente quando você injeta o escopo do Angular no html, você faz dessa maneira.

<html class="no-js" lang="pt-BR" ng-app="SeuApp">

O problema que a Biblioteca do Google Charts ou melhor, Google Visualization Library carrega um pouco atrasada ao comparada com a introspecção do DOM com o AngularJS, por que ela além de ser carregada dinamicamente de outro domínio, você ainda tem que esperar ele criar o objeto e assim fazer o parse dentro de um controller.

Acaba dando o seguinte erro.

 
Uncaught Error: [ng:btstrpd] App Already Bootstrapped with this Element '<body>'
http://errors.angularjs.org/1.2.16/ng/btstrpd?p0=%3Cbody%3E

Resumindo bem a história, você tem que esperar fazer o download da lib para máquina do cliente, e então só assim você pode usa-lá. Ah! Nem adianta você tentar baixar a biblioteca e rodar de forma off-line como lib em seu domínio, isso vai contra as regras de distribuição do Google e você(sua empresa) pode acabar se dando mal. Já que é contra os termos de uso.

Como fazer então?

Primeiro passo é remover o tag ng-app que define o escopo da sua aplicação no html principal.

Segundo passo, adicione o script do Google Charts em sua aplicação antes da inclusão do script do angularjs ou jquery, por exemplo.

<script src="https://www.google.com/jsapi" type="text/javascript"></script>

Terceiro passo, inclua a declaração da sua aplicação no loadCallBack(), que é o método usado pelo Google Charts para avisar que está pronto para ser utilizado.

/*global google*/
 
'use strict';
var app;
 
google.setOnLoadCallback(function() {
    angular.bootstrap(document.body, ['seuApp']);
  });
 
google.load('visualization', '1', {packages: ['corechart']});
 
var app = angular.module('seuApp', [
  'ngCookies',
  'ngResource',
  'ngSanitize',
  'ngRoute',
  'ngAnimate',
  'ngCollection',
  'ngGrid',
  'seuApp.services'
]);

Você fica acaba de ficar livre de um pequeno problema que facilmente você verá soluções utilizando directivas do Angular, ao invés de utilizar a própria lib em si.

Google Charts, não é uma preferência pessoal, é uma necessidade, já que imita muito as famosas Flex Charts, que tanto utilizei em diferentes BI por ai, a única forma que seria chata é justamente essa de esperar carregar.

Só que se me perguntarem qual solução de fato você usaria para documentos com gráficos, eu diria que a D3js.org seria minha preferência de imediato, já que me deixa totalmente livre do eixo x,y e explorar formas mais diversificada dados.

AngularJS/ HTML5 / CSS3/ Javascript/ JQuery

Criando um scroll Infinito com o AngularJS e JQuery

scrollinfinito-jquery

Esse post é o início de uma série de posts relacionados ao AngularJS, se você não conhece, é bom conhecer, muito de seu comportamento é semelhante ao que tinhamos no Flex, por exemplo Databind e a idéia de componentizar. E o mais legal de tudo é que ele é compatível com qualquer biblioteca que manipule o DOM, por exemplo Zepto e JQuery, ou até mesmo o Twitter Bootstrap.

O AngularJS facilita e muito certas tarefas e mantem o DRY bem vivo. Por exemplo, esse post eu quero falar sobre o scroll infinito, igual o comportamento que o Twitter possui ou o LinkedIn possui quando você vai rolando a página e dados vão pipocando em sua frente. Pois bem, como eu faria isso em puro Javascript e usando o seletor do DOM jQuery?

O scroll é um mal necessário, é o que a Microsoft tenta adotar na nova interface do Windows 8 e o que o Flex tentou quando lançou a versão 4.0. Porém é necessário trazer informações à medida que elas vão acontecendo ou carregar só o necessário e à medida que o usuário for investigando elas forem brotando.

scrollinfinito-jquery

Scroll Infinito com Javascript e JQuery.

O HTML é bem simples:

	<div id="conteudo">
    <ul id="lista"></ul>
</div
var contador = 1;
 
$(document).ready(function () {
    carregar();
    $(this).on('scroll', function () {
        if ($(window).scrollTop() + $(window).height() >= $(this).height()) {
            carregar();
        }
    });
});
 
function carregar() {
    for (var i = 0; i < 10; i++) {
        $("#lista").append('<li><img src="http://placehold.it/100x100"/><div><h4>' + contador + ' Item</h4><p>Descrição do item '+contador+'</p></div></li>');
        contador++;
    }
}

A medida que a soma da posição da barra mais a altura da janela superar o tamanho da altura do documento, ele executa a função carregar, jogando mais itens na lista.

O truque também está na maneira como você declara o CSS, margin faz um estrago danado quando não aplicada de forma correta, nesse exemplo eu coloquei uma aparência de uma lista de smartphone, igual no Android.

body, ul,li,img,h4,p{
    margin:auto;
    font-family:'Droid Sans';
}
ul {
	margin-left: -40px;
	list-style:none;
}
li {
    color:#111;
    height: 100px;
    border-bottom:1px solid #fff;
    padding:10px;
}
li h4 {
    font-weight:400;
    font-size:20px;
    padding:0;
}
li img {
    padding-right:10px;
    float:left;
    display:block;
    vertical-align:text-top;
}
li div {
    display:inline;
}
li p {
    font-weight:300;
    font-size:12px;
}
#conteudo {
    width:100%;
    background:rgba(0,0,0,0.1);
    overflow:auto;
}

E aqui está o exemplo rodando, eu usei o jsFiddle para demonstrar melhor.

Você pode ver sendo executado diretamente no jsFiddle

Criando agora uma lista infinita com o AngularJS

O AngularJS possui vários truques na manga para deixar sua vida mais fácil, módulos, tags personalizados, data-bind, repetidores, diretivas, controllers, esses são alguns de seus recursos. A melhor parte dele como mencionei acima é que é compatível com outras bibliotecas.

Para fazer esse exemplo você vai fazer uma pequena alteração no html e substituir o Javascript, os estilos que é o visual continuam o mesmo.

Logo de cara para identificar como um App, você precisa alterar o html e fazer da seguinte forma:

<!doctype html>
<html ng-app="Rolagem">
<head>

Isso define que o módulo Rolagem será seu App nesse arquivo de html, então na parte de repetir os itens você faz da seguinte forma.

<body ng-controller="Main">
	<div id="conteudo" fazer-rolagem="carregar()">
    <ul id="lista">
         <li ng-repeat="i in items">
            <img src="http://placehold.it/100x100"/>
            <div><h4>{{i.id}} Item</h4>
            </div>
        </li>
    </ul>
</div
</body>

Como o AngularJS abstrai bastante o escopo do javascript para com o HTML, é notável algumas propriedades como o ng-controller, fazer-rolagem que são primariamente customizáveis, a presença do ng-repeat indica que o arquivo vai ser repetido N vezes, conforme vamos adicionando novos itens à lista.

E a parte fundamental desse processo é o Javascript:

function Main($scope) {
    $scope.items = [];
 
    var counter = 1;
    $scope.carregar = function() {
        for (var i = 0; i < 10; i++) {
            $scope.items.push({id: counter});
            counter += 1;
        }
    };
 
    $scope.carregar();
}
 
angular.module('Rolagem', []).directive('fazerRolagem', function() {
         return function(scope, elm, attr) {
        elm = $(document);
 
        elm.bind('scroll', function() {
             if ($(window).scrollTop() + $(window).height() >= $(this).height()) {
                 scope.$apply(attr.fazerRolagem);
             }
        });
    };
});

Agora você já sabe como criar uma diretiva, fazer um módulo e carregar os itens conforme forem feitos os scrolls, no JQuery quando você quer escutar um evento você geralmente usa o $on(), no AngularJS é necessário usar o bind, ele que vai escutar pelo evento.

Maneiras diferentes de aplicar a mesma técnica, para um resultado igual, Eu gostei mais do AngularJS, escrevi menos código e atingir o mesmo resultado.

Ah! lembrando que esses códigos estão disponíveis no Github.