Arquivos da categoria: Javascript

O que é: SPA – Single Page Application e REST/RESTFul

SPASPA – Single Page Application é uma novo modelo de desenvolvimento de aplicações Web e mobile que vem ganhando destaque em grandes empresas como Microsoft, Google, Twitter, Facebook, etc.

SPA basicamente significa codificar menos no server-side e mais no client-side. Ou seja, a aplicação estará contida toda ou quase toda no cliente (dentro do navegador Web). É praticamente uma aplicação Desktop rodando sob o navegador.

Vantagem:

1 – balanceamento da responsabilidade da execução entre cliente e servidor (agora não é só mais responsabilidade do servidor);
2 – menos código do servidor, e mais responsabilidade no cliente;
3 – melhorar a experiência ao usuário (UX) criando interface com usabilidade moderna e de fácil entendimento do usuário;
4 – menor consumo de banda, pois as cargas de dados são feitas por demanda e por AJAX.

O grande ator de app SPA é o código Javascript executado no cliente. Toda a aplicação pode ser construída simplesmente manipulando o DOM – Document Object Model de forma nativa, ou com o uso de bibliotecas e frameworks Javascript que auxiliam na construção da aplicação. Estas bibliotecas e frameworks fornecem recursos para manipulação dinâmica do DOM, definição de templates de tela, chamadas assincronas ao servidor, organização do código Javascript, etc. Dentres as diversas bibliotecas JS que surgem a todo momento, as mais difundidas na comunidade de progamadores estão: BACKBONE, EMBER, ANGULARJS e KNOCKOUT.

No lado servidor, temos a execução das linguagens tradicionais como PHP, ASP.NET, JSP, etc, trabalhando também de forma tradicional, servindo arquivos, acessando a banco de dados, tratando as regras de negócios que não podem estar no código JS por questões de segurança. E é neste lado (servidor) que podemos utilizar a arquitetura REST – Representational State Transfer para fornecer serviços do servidor para nossa aplicação SPA. É comum encontrar aplicação SPA utilizando serviços RESTFul. Uma aplicação no servidor que utiliza a arquitetura REST para servir serviços, então é chamada de RESTFul.

Ao construir uma aplicação utilizando a arquitetura REST, o protocolo HTTP é usado em sua essência, utilizando os verbos (ou métodos de requisição ao servidor): GET, POST, PUT e DELETE (estes são os mais comuns), e cada um deles indica uma determinada ação a ser executada em um recurso específico do servidor.

  • GET: Está requisitando ao serviço um determinado recurso, por exemplo, uma listagem de dados;
  • POST: Indica ao serviço que a ele deve receber o recurso que está sendo enviado e adicionar em algum repositório;
  • PUT: Indica que ao serviço que o recurso que está sendo enviado deve ser alterado se ele já existir, ou ainda, pode ser adicionado caso ele ainda não exista;
  • DELETE: Indica que o serviço deve excluir o recurso.

Pensando em banco de dados, temos o seguinte entendimento:

  • GET: Recupera dados [select];
  • POST: Realiza a inserção de dados [insert];
  • PUT: Realiza a alteração de dados [update];
  • DELETE: Realiza a exclusão de dados [delete].

AngularJS – Rotas

pic_angularOlá pessoal. Dando continuidade ao meu estudo sobre o angular, agora vamos de rota.

Numa aplicação SPA – Single Page Application usando o AngularJS, a navegação entre as views da app ocorrem sem requisições ao servidor, e baseada em rotas interna da própria app.

Para criar rotas em nossa app, o cenário perfeito é ter um arquivo principal de configuração. Por exemplo: app.js:

//criando um módulo global app com dependência ao pacote ngRoute
var app = angular.module('app', ['ngRoute']);

//definindo as rotas
app.config(function ($routeProvider, $locationProvider) {

    // remove o # da url, padrão
    $locationProvider.html5Mode(true);

    $routeProvider.when('/', { templateUrl: '/Views/lancamentos.html' });

    $routeProvider.when('/index.html', { templateUrl: '/Views/home.html' });

    $routeProvider.when('/lancamentos', { templateUrl: '/Views/lancamentos.html'});

    $routeProvider.when('/tp-lancamento', { templateUrl: '/Views/tp-lancamento.html'});

});

O objeto $routeProvider em seu método WHEN faz o registro da rota, sendo o primeiro parâmetro a rota de fato e o segundo, um objeto literal indicando da propriedade templateUrl o destino da rota. Por exemplo, toda chamada da app que ocorrer para “/lancamentos”, o conteúdo apresentado será o contido em “/Views/lancamentos.html”.

O link HTML para chamar o conteúdo da rota ficará assim:

<ul>
    <li><a href="lancamentos">Lançamentos</a></li>
    <li><a href="tp-lancamento">Tipos de Lançamento</a></li>
</ul>

O resultado do redirecionamento é o conteúdo do arquivo HTML referenciado pela rota. Este conteúdo deve ser depositado num contêiner que é marcado pela diretiva ng-view.

Exemplo:

<head>
    <script src="angular.min.js"></script>
    <script src="angular-route.min.js"></script>
    <script src="app.js"></script>
    <script src="Controllers/tpLancamento.js"></script>
    <script src="Controllers/lancamentos.js"></script>
</head>
<body>
   <ul>
       <li><a href="lancamentos">Lançamentos</a></li>
       <li><a href="tp-lancamento">Tipos de Lançamento</a></li>
   </ul>
   
   <div ng-view>
       <!--Conteúdo da view será carregado aqui--> 
   </div>
</body>

No código acima, observe a importação do arquivo “angular-route.min.js” responsável por manter o pacote ngRoute, utilizado no app.config. Também foi importado o arquivo app.js e os controladores para views.

AngularJS – Formulário

pic_angularOlá pessoal. Agora relato o que aprendi sobre formulários HTML com AngularJS.

O AngularJS fornece implementações básica de validação para a maiorias de input HTML5 (text, number, url, email, date, radio, checkbox), além de algumas diretivas de validação: required, pattern, minlength, maxlength, min, max, email, number, etc…).

As implementações básicas de validação estão descritas aqui: Angular input directive.

Detalhes sobre as validações dos inputs podem ser obtidos diretamente na referência oficial:

O framework também oferece propriedades booleanas que ajudam a validar os formulário e seus campos, dando informações sobre o a entrada de dados.

  • $dirty: Indica se o usuário interagiu com o formulário/campo.
  • $pristine: Indica se o usuário ainda não interagiu com o formulário/campo.
  • $valid: Indica se o formulário/campo possui valor válido.
  • $invalid: Indica se o formulário/campo campo possui valor válido.

As propriedades são acessadas no formulário (geral para todos os campos) ou diretamente no elemento (input, select ou textarea). Segue a seguinte nomenclatura:

  • Para formulário: <form name>.<angular propriedade>
  • Para o elemento de entrada: <form name>.<input name>.<propriedade>

Perante a todas estas informações descritas acima, demonstro um pequeno exemplo de validação de formulário.

HTML:

<form name="formDados" novalidate>
    <!--novalidate: necessário para anular as validações nativas do navegador para HTML5-->

    <select ng-model="lancamento.tipo" name="tipo" required>
        <option value="0">selecione...</option>
        <option ng-repeat="t in tipos" value="t.id">{{t.descricao}}</option>
    </select>
    <!--Validando se o valor é vazio (requerido)-->
    <span ng-show="formDados.tipo.$error.required">O TIPO é requerido.</span>
    <br />

    <input type="date" ng-model="lancamento.data" placeholder="data" name="data" required />
    <!--Validando se o valor é vazio (requerido) e a quantidade máxima de caracteres-->
    <span ng-show="formDados.data.$error.required">A DATA é requerida.</span>
    <span ng-show="formDados.data.$error.date">A DATA é inválida.</span>
    <br />

    <input type="text" ng-model="lancamento.obs" placeholder="observação" name="obs" required ng-maxlength="20" />
    <!--Validando se o valor é vazio (requerido) e a quantidade máxima de caracteres-->
    <span ng-show="formDados.obs.$error.required">A OBSERVAÇÃO é requerida.</span>
    <span ng-show="formDados.obs.$error.maxlength">A OBSERVAÇÃO deve ter no máximo 20 caracteres.</span>
    <br />

    <input type="number" ng-model="lancamento.valor" placeholder="valor" name="valor" min="0" />
    <!--Validando o valor é numérico-->
    <span ng-show="formDados.valor.$invalid">Não é um número válido.</span>
    <br />

    <!--O botão ficará desabilitado (ng-disabled) de o usuário não interagir com os campos tipo, obs e valor-->
    <input type="button" value="salvar" id="salvar" ng-click="salvar()"
            ng-disabled="!formDados.tipo.$dirty || !formDados.obs.$dirty || !formDados.valor.$dirty" />

</form>

Javascript (controller):

app.controller('LancamentosController', ['$scope', function ($scope) {

    $scope.tipos = [];
    
    $scope.lancamento = {
        tipo: 0,
        data: "",
        obs: "",
        valor: "", 
        cpf: ""
    };

    $scope.init = function () {
        //carregando os tipos
        if (localStorage.getItem("tps") != null) {
            $scope.tipos = JSON.parse(localStorage.getItem("tps"));
        }
    };

    $scope.salvar = function () {
       
        //testando se o formulário é valido
        if (!$scope.formDados.$valid) {
            
            alert('Verifique os campos');
        }
        else{
            alert('salvou');
        }
    }

    $scope.init();

}]);

É BOM OBSERVAR: O formulário e os elemento de entrada de dados possuem o atributo name, pois será utilizado para implementação das validações. As tags span com a mensagem da invalidação somente será mostrada (ng-show) conforme o retorno booleano da diretiva de validação.

Quando as validações nativas do AngularJS não atendem alguma regra do sistema, é por meio de diretivas que podemos criar validações customizadas. O exemplo abaixo implementa a validação customizada para validar CPF (o algoritmo de validação do CPF não foi disponibilizado por questão de espaço).

Javascript:

app.directive('cpfValido', function () {
    return {
        restrict: 'A',
        require: 'ngModel',
        link: function (scope, elem, attrs, ctrl) {

            scope.$watch(attrs.ngModel, function () {

                if (elem[0].value.length == 0)
                    ctrl.$setValidity('cpfValido', true);
                else if (elem[0].value.length < 11) {
                    //aplicar o algoritmo de validação completo do CPF
                    ctrl.$setValidity('cpfValido', false);
                }
                else ctrl.$setValidity('cpfValido', true);
            });
        }
    };
});

HTML:

<input type="text" ng-model="lancamento.cpf" name="cpf" cpf-valido />
<span ng-show="formDados.cpf.$error.cpfValido">CPF Inválido</span>
	

https://docs.angularjs.org/guide/forms

AngularJS – Diretivas

pic_angularOlá pessoal. Dando continuidade ao meu estudo sobre o angular, deixo aqui registrado o que estudei e entendi sobre diretivas.

Diretivas dão poder ao programador para estender/ampliar o comportamento de elementos HTML, e é responsável pela manipulação do DOM. Uma diretiva é capaz de selecionar um elemento HTML por seu atributo (associado ao nome da diretiva), ou nome do elemento, ou por um comentário, ou mesmo pelo valor do atributo class.

Ao selecionar um elemento HTML, a diretiva pode ampliar seu comportamento, adicionando um novo HTML, manipulando o DOM, ou ainda associando eventos à funções Javascript.

São diversas as diretivas nativas do angular: ng-controller, ng-model, ng-repeat, ng-show, ng-hide, ng-click, ng-blur, ng-change, ng-checked, ng-focus, ng-keydown, ng-keypress, ng-keyup, e diversas outras.

Podemos criar nossas próprias diretivas (Custom Directives), para por exemplo:

    • Criar componentes como: abas, janelas de mensagens, janelas pop-up, calendário, etc…;
    • Intercecptar a vinculação de dados e tratá-los se necessário;
    • Criar uma esquema padronizado para validação do model;
    • Tratar eventos dos elementos HTML;
    • Etc…

Uma diretiva customizada deve estar associada a um módulo, podendo ser o próprio módulo da página:

<body ng-app="myApp">
    <div minha-diretiva></div>
</body>
var app = angular.module('myApp', []);

app.directive('minhaDiretiva', function () {
   return {
	restrict: 'A',
	link: function (scope, elem, attrs) {
		elem[0].innerHTML = "minha diretiva....";
	}
   }
});

No exemplo acima, a função directive() do módulo, é usada para criar uma diretiva chamada “minhaDiretiva”, retornando um objeto literal com suas definições. A propriedade restrict é usada para especificar como a diretiva irá selecionar o elemento HTML. Os valores válidos para restrict são:

  • ‘A’ – Atributo:
  • ‘E’ – Elemento:
  • ‘C’ – Class:
  • ‘M’ – Comentário:

A propriedade link deve ser associada a uma função de ligação que faz o trabalho de definição da diretiva. Parâmetros da função: scope, elem e attrs.

  • scope: dá acesso ao escopo da diretiva;
  • elem: é um objeto JQuery Lite contendo o elemento encontrado pela diretiva;
  • attrs: é um objeto que mantém todas as propriedades do objeto encontrado pela diretiva.

O resultado final após a execução da diretiva é:

<div minha-diretiva="">minha diretiva....</div>

Agora vou alterar a diretiva anterior para localizar elementos HTML pelo nome (customizado) da tag do elemento. Com angular, posso criar meus tipos de elemento HTML e definir seu comportamento.

<body ng-app="myApp">
    <minha-diretiva></minha-diretiva>
</body>
var app = angular.module('myApp', []);

app.directive('minhaDiretiva', function () {
   return {
	restrict: 'E',
	link: function (scope, elem, attrs) {
		elem[0].innerHTML = "minha diretiva....";
	}
   }
});

O resultado final é:

<minha-diretiva>minha diretiva....</minha-diretiva>

Observação: é padrão no angular o nome da diretiva seguir a nomenclatura: “primeira palavra iniciando em minusculo e demais com inicial maiúscula”, por exemplo: minhaDiretiva, janelaMensagem, etc. No momento de usar (no HTML) fica assim (dash-delimited): minha-diretiva, janela-mensagem, etc.

Utilizando o conceito de diretivas, também é possível criar templates utilizando as propriedades template ou templateUrl do objeto de retorno de definição da diretiva.

Avançando um pouco mais, mas nem tanto. Uma diretiva também pode ser um template. Observe:

<span meu-template="meu primeio template...">
app.directive('meuTemplate', function () {

    return {

        restrict: 'A',
        scope: {},
        link: function (scope, elem, attrs) {
            scope.msg = attrs.meuTemplate;
        },
        template: '<div><strong>{{msg}}</strong></div>',
        replace: false
    }
});

Ao usar a diretiva acima, obtém-se o seguinte resultado após a renderização:

<span meu-template="meu primeio template...">
    <div>
	 <strong>meu primeio template...</strong>
   </div>
</span>

O conteúdo da propriedade template da diretiva foi incluído dentro do elemento span selecionado pela diretiva. Isso ocorreu devido a propriedade replace estar configurada como false. Se configurado com true, o elemento span é totalmente substituído pelo conteúdo do template, observe o resultado da renderização:

<div meu-template="meu primeio template...">
   <strong>meu primeio template...</strong>
</div>

Há também no objeto de definição da diretiva para elementos (restrict: ‘E’) uma propriedade chamada transclude, que é capaz e anexar/incluir elementos (do contêiner selecionado pela diretiva) dentro do template da diretiva.

E para finalizar, segue um exemplo (simplório) de diretiva para mostrar áreas de mensagens.

app.directive('msgAlert', function () {

    return {
        restrict: 'A',
        scope: { textoMsg: '@'},
               
        template: '<div class="msgAlert">{{textoMsg}} <input type="button" value="(fechar)" ng-click="esconder()" /></div>',
        replace: true,
               
        link: function (scope, elemento, attrs) {
            scope.esconder = function () {
                scope.$parent.mostrarAlert = false;
            }
        }
    };
});

<style>
    .msgAlert {
        background-color:#ffd800;
        border: 1px solid #808080;
        padding: 5px;
        margin: 5px;  
   }
</style>

<div msg-alert texto-msg="{{msg}}" ng-show="mostrarAlert"></div>
<input type="button" value="mostrar alerta" ng-click="abrirAlert()" />

Conclui que usar diretivas não é tão fácil. :-(

AngularJS – Introdução

pic_angularOlá pessoal, inicio aqui meu aprendizado no tão falado framework do Google, o AngularJS. Os textos aqui representam o que tenho estudado e aprendido a respeito deste framework.

AngularJS é um framework Javascript open-source mantido pela Google que dá poder aos desenvolvedores para criar aplicações Web baseadas em navegadores, como as aplicações SPA – Single Page Application.

O site oficial é https://angularjs.org/.

Vamos ao Olá Mundo!!!

<html>
<head>
    <title>Olá Mundo</title>
    <script src="angular.min.js"> </script>
    <script>
        var app = angular.module('minhapagina', []);
    </script>
</head>
<body ng-app="minhapagina">
    <p>Olá mundo: {{ 1 + 2 }}</p>
</body>
</html>

O exemplo acima, consiste em uma simples página HTML, a não ser pelo atributo ng-app. Os “angularianos” chamam ng-app de diretiva, e normalmente é aplicada a tag BODY ou HTML, e indica o elemento inicial da aplicação (ponto a partir do qual o Angular pode ser usado dentro do código HTML).

O código javascript destacado no exemplo, localiza a diretiva ng-app, transformando a página num módulo gerenciável pelo o framework.

 
var app = angular.module('minhapagina', [])

O texto “{{ 1 + 2 }}” é avaliado como uma expressão pelo Angular, que ao ser executada, o resultado é concatenado ao HTML do contexto que está inserida. Uma expressão deve estar entre chaves duplas.

Outras principais diretivas:

ng-controller: define uma função Javascript para controlar determinada parte da página;
ng-model: vincula o elemento a uma propriedade do model do seu contexto;
ng-repeat: realiza a iteração em um array (basicamente um foreach);
ng-show: deixa visível um elemento HTML de acordo com um valor booleano (true/false). Também aceita expressões lógicas;
ng-hide: esconde o elemento de acordo com um valor booleano (true/false). Aceita expressões lógicas;

A referência completa das diretivas é obtida em https://docs.angularjs.org/api/ng/directive/.

Existem diretivas para tratar os diversos eventos disponibilizados nos elementos HTML: ng-click, ng-blur, ng-change, ng-checked, ng-focus, ng-keydown, ng-keypress, ng-keyup, e diversas outras.

O angularJS e o padrão MVC.

Normalmente encontramos a implementação do padrão MVC na programação que ocorre no lado do servidor da aplicação. Com o angular é diferente, a implementação ocorre no lado cliente da aplicação.

O padrão MVC é composto por três componentes principais:

Model – Componente responsável por gerenciar os dados para a aplicação. Não é de responsabilidade do model como o usuário vê os dados e qual lógica será aplicada sobre eles.

View – Componente que representa visualmente o model, um pedaço do HTML da página. Exibe os dados para o usuário devidamente organizados em estruturas HTML e CSS. Não é de sua responsabilidade a lógica contida no controller nem no model.

Controller – Componente responsável por preparar o model para a view, além de tratar regras de negócios, tratar eventos da view e requisições ao servidor.

angular_mvc

Vamos a um segundo exemplo.

<script>
   var app = angular.module('minhapagina', []);
</script>
<body ng-app="minhapagina">
     Seu primeiro nome é: <input type="text" ng-model="primeironome" />
     <p>{{primeironome}}</p>
</body>

Entendendo o exemplo: a diretiva ng-model vincula o valor de elementos input, select e textarea a uma propriedade no model chamada “primeironome”. Neste exemplo, a propriedade “primeironome” do model, mantém o valor informado no input, sendo possível, por exemplo, dentro da view usar expressões para recuperar seu valor.

Efeito igual é conquistado usando a diretiva ng-bind, que auto alimenta a propriedade innerHTML do elemento HTML com o valor de uma propriedade do model.

<p ng-bind="primeironome"></p>

Por questão de padronização do HTML e para deixar válido junto ao W3C, é possível utilizar o prefixo data- (dataset do HTML5) antes das diretivas:

data-ng-app
data-ng-model=”primeironome”
data-ng-bind

Vamos entender melhor a diretiva ng-controller.

Um controller é atribuído a um pedaço da página HTML (view) através da diretiva ng-controller. O controller é uma função Javascript (do tipo construtora) que tem por objetivo cuidar e atualizar de uma determinada área do DOM do página (um pedaço da página, a view).

Como regra geral, um controlador não deve fazer referência ou manipular o Document Object Model (DOM) diretamente.

Controllers são responsáveis pela interação entre models e views. A vinculação de dados entre model e view é realizada pelo angularJS de forma dinâmica, ou seja, qualquer alteração ocorrida em um dos lados (model ou view) atualiza o outro lado, é o chamado Two-Way DataBing [atualização de duas vias] (isso pode ser observado no primeiro exemplo: ao digitar no input, a propriedade “primeironome” é atualizada simultaneamente).

O acesso à view pelo controller é realizado através do objeto $scope. O $scope é um parâmetro do controller que dá acesso ao model vinculado a view.

Vamos a um simples exemplo sobre Controller.

HTML:

    <div ng-controller="MinhaControladora">
        <input type="button" ng-click="perguntar()" value="OK" />
        <p ng-bind="nome"></p>
    </div>

JS:

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

app.controller('Controladora1', ['$scope', function ($scope) {

	$scope.nome = "...";

	$scope.perguntar = function () {
		$scope.nome = prompt("Qual seu nome?");
	};
}]);

Analisando o bloco da função controladora acima, foi definido a propriedade “nome” e o método “perguntar”. O parâmetro $scope estabelece uma conexão entre a model e view. No bloco HTML representando a view, as propriedades e métodos do models podem ser acessadas e vinculados aos elementos HTML.

Vamos a um exemplo menos simples (mas não avançado) sobre Controller. Destaque para a diretiva ng-repeat para iterar um array.

Javascript:

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

app.controller('principal', ['$scope', function ($scope) {

	$scope.item = "";
	$scope.msg = "";
	$scope.itens = [];

	$scope.adicionar = function () {


		if ($scope.item == "") {
			alert("Informe o texto");
		}
		else {


			if ($scope.itens.indexOf($scope.item) == -1) {
				$scope.itens.push($scope.item);
				$scope.msg = "";
				$scope.item = "";
			}
			else {
				$scope.msg = "Item existente.";
			}
		}
	};

	$scope.excluir = function (item)
	{
	
		var pos = -1;
		for (var i = 0; i < $scope.itens.length; i++) {

			if ($scope.itens[i] == item)
			{
				pos = i;
				break;
			}
		}

		if (pos > -1)
			$scope.itens.splice(pos, 1);
	}
}]);

HTML:

<body ng-app="myApp" ng-controller="principal">
    <input type="text" ng-model="item" />
    <input type="button" ng-click="adicionar()" value="adicionar" />
    <div mostrar-msg></div>
    <table>
        <thead>
            <tr>
                <th>Item</th>
                <th>&nbsp;</th>
            </tr>
        </thead>
        <tbody>
            <tr ng-repeat="item in itens">
                <td>{{item}}</td>
                <td><a href="javascript:;" ng-click="excluir(item)">excluir</a></td>
            </tr>

        </tbody>
    </table>
    <div>{{msg}}</div>
</body>

 

É por aqui que finalizo meu estudo inicial sobre o Angular. Espero nos próximos post destacar o uso de templates, criação de diretivas próprias e AJAX com o AngularJS.

 

Referencial utilizado

  • AngularJS Succinctly [https://www.syncfusion.com/resources/techportal/ebooks]
  • Site Oficial [angularjs.org]
  • Ultimate guide to learning AngularJS in one day [http://toddmotto.com/ultimate-guide-to-learning-angular-js-in-one-day/]
  • AngularJS Tutorial [http://www.w3schools.com/angular/default.asp]

AngularJS – Requisições Assíncronas (AJAX)

pic_angularEste post foi construído com base na documentação oficial: https://docs.angularjs.org/api/ng/service/$http.

A comunicação entre cliente e servidor no AngularJS é gerenciada pelo serviço $http.

Os métodos disponíveis para realizar requisições são:

  • $http.get
  • $http.head
  • $http.post
  • $http.put
  • $http.delete
  • $http.jsonp
  • $http.patch

Por padrão, estes métodos estão configurados com o Content-Type “application/json;charset=UTF-8”.

Vamos a um simples exemplo que obtém uma cidade a partir de um UF selecionado.


var myApp = angular.module("myApp", []);

myApp.controller("carregaCidade", ['$scope','$http', function ($scope, $http) {

	$scope.uf = "";
	$scope.cidades = [];
	$scope.buscarCidades = function () {

		var params = "?UF=" + $scope.uf;
		var $http.req = get("BuscarCidades.aspx" + params , dados);

		req.success(function (retornoServidor, status) {
			$scope.cidades = retornoServidor;
		});

		req.error(function (retornoServidor, status) {

	   });
	};
}]);
<body ng-app="myApp">
    <div ng-controller="carregaCidade">

		<select id="ddlUf" name="uf" ng-model="uf" ng-change="buscarCidades()">
			<option selected="selected" value="">Selecione</option>
			<option value="SP">SP</option>
			<option value="AC">AC</option>
			<!--...-->
			<option value="TO">TO</option>
		</select>

		<select id="ddlCidades" name="ddlCidades">
			<option value="">selecione...</option>
			<option ng-repeat="cidade in cidades" value="{{cidade.Id}}">{{cidade.Nome}}</option>
		</select>
	
  </div>
</body>	

Os eventos success e error tratam o resultado da operação.

É possível usar diretamente o serviço $http fazendo toda a configuração manualmente.

var req = $http({
   method: "GET",
   url: "BuscarCidades.apsx" + params
});

req.success(function (data, status, headers, config, statusText) {
	$scope.cidades = data;
   
});

req.error(function (data, status, headers, config, statusText) {
	console.log(status);
});

Os exemplos acima utilizaram o método de envio GET, passando dados diretamente pela URL. Para usar o método POST também é simples, bastando organizar os dados para envio no formato JSON.

var dados = JSON.stringify({ UF: $scope.uf });
 
var req = $http({
	url: "BuscarCidades.aspx",
	data: dados,
	method: "POST",
	headers: "Content-Type: application/json;charset=UTF-8"

});

Ou

var req = $http.post("BuscarCidades.aspx", dados);

É claro, que pensando no conceito de aplicações que usam a arquitetura REST, este tipo de requisições (busca de dados) deve ser sempre GET.

Chamadas XMLHttpRequest (AJAX) enviando JSON para páginas aspx ou GenericHandler – Deserialização manual

json160 csharplogoOlá pessoal,

Realmente é muito simples realizar uma chamada XMLHttpRequest (AJAX) para um WebMethod ASP.NET. E mais fácil ainda é enviar dados no formato JSON para o WebMethod, pois por padrão o WebMethod deserealizada a string JSON conforme seus parâmetros.

Mas quando não temos um WebMethod para receber os dados no formato JSON e fazer todo o trabalho de sujo de deserialização? Por exemplo, ao fazer chamadas XMLHttpRequest para uma página ou um Generic Handler passando dados no formato JSON. Nesta situação é necessário realizar a deserialização dos dados manualmente, vamos a um exemplo.

Chamada XMLHttpRequest no lado cliente:

var request = $.ajax({
type: &quot;POST&quot;,
dataType: &quot;json&quot;,
url: &quot;/meusite/processa.ashx&quot;,
cache: false,
data: JSON.stringify({ p1: &quot;oi&quot;, p2: 1000, vet: [{ vp1: {vp2: &quot;xxxx&quot;}},2] })

});

request.done(function (r) {
console.log(r);
});

request.fail(function () {
alert(&quot;Não foi possível processar sua requisição.&quot;);
});

O código acima utiliza a biblioteca jQuery para encapsular o uso da biblioteca javascript XMLHttpResquest e enviar dados ao servidor. Em sua configuração, a propriedade “URL” indica um GenericHandler no servidor (processa.ashx), mas que também pode ser substituído por uma página aspx. E a propriedade “data” foi configurada com um objeto literal com propriedades simples e complexas, que antes de ser enviado ao servidor será transformando numa string JSON pelo método JSON.stringify.

No lado servidor (no GenericHandler ou no método page_load da página), a recepção dos dados fica assim:

JavaScriptSerializer jss = new JavaScriptSerializer();
string json = new StreamReader(context.Request.InputStream).ReadToEnd();

Dictionary&lt;string, object&gt; values = jss.Deserialize&lt;Dictionary&lt;string, object&gt;&gt;(json);

string p1 = values[&quot;p1&quot;].ToString();
int p2 = Convert.ToInt32(values[&quot;p2&quot;]);

var vet = (ArrayList)values[&quot;vet&quot;];
var vp1 = ((Dictionary&lt;string, object&gt;)vet[0])[&quot;vp1&quot;];
var vp2 = ((Dictionary&lt;string, object&gt;)vp1)[&quot;vp2&quot;];

No código de servidor acima, a propriedade InputStream do objeto Request representa o conteúdo do corpo de entrada de conteúdo HTTP vindo do cliente, portanto, representa a string JSON enviada pelo cliente.

O inputString é recuperado e deserializado em um objeto Dictionary (espécie de lista indexada por chaves). Cada propriedade da string JSON torna-se uma chave do dicionário, sendo facilmente acessada:

int p1 = values[&quot;p1&quot;].ToString();
int p2 = Convert.ToInt32(values[&quot;p2&quot;]);

E também podemos acessar estruturas JSON mais complexas, como é o caso da propriedade “vet”, que mantém um vetor, cujo seu índice 0 (zero) contém outro objeto JSON.

vet: [{ vp1: {vp2: &quot;xxxx&quot;}},2]

Após recuperação do vetor, foi necessário converte o objeto de índíce 0 (zero) em outro Dictionary, desta forma, as propriedades do objeto contido no índice 0 (zero) da propriedade “vet” são acessadas por chaves do Dictionary.

var vp1 = ((Dictionary&lt;string, object&gt;)vet[0])[&quot;vp1&quot;];
var vp2 = ((Dictionary&lt;string, object&gt;)vp1)[&quot;vp2&quot;];

E fim.

Gerando estruturas JSON em C# e ASP.NET

json160Dando continuidade ao post Introdução ao JSON – Javascript Object Notation, mostro agora como construir em C# as estruturas dos exemplos utilizados no post anterior.

No C# podemos criar objetos de tipo anônimos (anonymous types) para definir a estrutura e dados, e depois realizar a serialização para o formato JSON.

Vamos aos exemplos:

1 – Criando um objeto.

public static string retornaObjetoJSON()
{
    //{“nome” : “Bill”, “idade” : 32, “salario”: 121232.67}

    var obj = new { nome = "Bill", idade = 32, salario = 121232.67};

    JavaScriptSerializer js = new JavaScriptSerializer();
    string strJson = js.Serialize(obj);
    return strJson;
}

2 – Criando um array.

public static string retornaArrayJSON()
{
    //["Huguinho","Zezinho","Luizinho", 3]

    var objVet = new object[] { "Huguinho", "Zezinho", "Luizinho", 3 };

    JavaScriptSerializer js = new JavaScriptSerializer();
    string strJson = js.Serialize(objVet);
    return strJson;
}

3 – Criando um array de objetos.

public static string retornaVetorDeObjetoJSON()
{
    /*
        [{ "nome" : "Huguinho", "idade" : 10 },
        { "nome" : "Zezinho", "idade" : 12 },
        { "nome" : "Luizinho", "idade" : 10 }]
    */

    var objVet = new object[] { new { nome = "Huguinho", idade = 10 },
                                new { nome = "Zezinho", idade = 12 },
                                new { nome = "Luizinho", idade = 10 }};

    JavaScriptSerializer js = new JavaScriptSerializer();
    string strJson = js.Serialize(objVet);
    return strJson;
}

4 – Criando um objeto contendo um propriedade array de objetos.

public static string retornaObjetoComVetorJSON()
{
    /*
        {"tio" : "Pato Donald",
        "idade" : 40,
        "sobrinhos" :
                [{ "nome" : "Huguinho",     "idade" : 10 },
                { "nome" : "Zezinho", "idade" : 12 },
                { "nome" : "Luizinho", "idade" : 10 }]
        }
    */

    var obj = new {tio = "Pato Donald",
                    idade = 40,
                    sobrinhos = new object[] { new { nome = "Huguinho", idade = 10 },
                                                new { nome = "Zezinho", idade = 12 },
                                                new { nome = "Luizinho", idade = 10 }}
                    };

    JavaScriptSerializer js = new JavaScriptSerializer();
    string strJson = js.Serialize(obj);
    return strJson;
}

A biblioteca System.Web.Script.Serialization é a responsável por realizar a serialização dos objetos anônimos.

Logo mais num outro post mostro como realizar chamadas assíncronas por Javascript ao JSON gerado no C# no servidor.

Até…

Validações customizadas com HTML5

HTML5_Logo_512Quando as validações prontas do HTML5 não são suficientes, temos que fazer as nossas.

Em HTML5 temos um novo evento, oninput,  que pode ser associado a um input, e é disparado quando seu valor é modificado. Seu disparo deve ser associado a uma função Javascript para fazer a validação do valor informado no input.

Na função de validação o método setCustomValidity do input recebe uma string. Se vazia, significa que o dado está válido, caso contrário, o navegador mostrará a mensagem informada ao método.

Vamos a um exemplo:

&lt;head&gt;
    &lt;meta charset=&quot;utf-8&quot; /&gt;
    &lt;title&gt;&lt;/title&gt;
    &lt;script&gt;

        function validaCPF(input){

            if (input.value.length &gt; 11 || input.value.length &lt; 11)
                input.setCustomValidity('CPF inválido');
            else input.setCustomValidity('');

        }

    &lt;/script&gt;
&lt;/head&gt;
&lt;body&gt;
    &lt;form&gt;

            CPF:
            &lt;input type=&quot;text&quot; id=&quot;cpf&quot; name=&quot;cpf&quot; oninput=&quot;validaCPF(this)&quot;&gt;
            &lt;input type=&quot;submit&quot; id=&quot;enviar&quot; name=&quot;enviar&quot; value=&quot;Enviar&quot;&gt;
    &lt;/form&gt;
&lt;/body&gt;

 

Se seu querido navegador der suporte ao novo evento, algo como mostrado na imagem abaixo deve aparecer.

evento_oninput

 

 

Simples e eficiente.