ToDoVel [Parte 11] Marcando as Tasks Como Concluídas

Observação: Este tutorial refere-se ao Laravel-4-BETA, estando totalmente DESATUALIZADO para a versão atual. Muita coisa mudou no framework…

Agora que estamos listando as tasks que criamos seria bom saber as tasks que já concluímos através da simples ação de concluí-las.
Para isso, vamos dar uma melhorada no layout da listagem dos tasks e, utilizando Jquery + AJAX, vamos realizar a ação de concluir as tarefas.

Criando Uma Nova Seção no Template

Vou fazer uma alteração lá no arquivo template.blade.php.
Vou criar uma seção onde as outras views podem colocar seus scripts JavaScript customizados.
Então, lá no finalzinho do arquivo antes da tag /body eu coloco:

    <script src="assets/js/bootstrap-collapse.js"></script>
    <script src="assets/js/bootstrap-carousel.js"></script>
    <script src="assets/js/bootstrap-typeahead.js"></script>

    @section('custom_script')
    @show

  </body>

Melhorando a Exibição de Tasks

Vou alterar a view que exibe as tasks para fazer duas coisas:

  • A primeira para exibir diferenciado: quando for uma task não concluída, exibir um checkbox. Quando for uma task concluída, exibir a task com um estilo legal do TwitterBootstrap
  • A segunda é colocar dentro da nova seção, custom_script, o script Jquery/JavaScript que irá escutar o evento de alteração do checkbox da task e executará o AJAX
@extends('template')

@section('conteudo')
    
    <ul style="list-style: none;">
        @foreach ($tasks as $task)
            <li class="task">
                @if ($task->status)
                    <span class="label label-success">{{ $task->titulo }}</span>
                @else
                    <label data-task-id='{{ $task->id }}'>
                        <input type="checkbox" />
                        {{ $task->titulo }}
                    </label>
                @endif
            </li>
        @endforeach
    </ul>
@stop


@section('custom_script')
    <script language="javascript">
        $(document).ready( function() {

            $('li label input').on('change', function(){
                var task_id = $(this).parent().data('task-id');
                var li = $(this).parent().parent();

                //ajax post request
                $.post(
                    "/task/check",
                    {task_id: task_id},
                    function(data) {
                        //callback do ajax request
                        if (data.status == true) {
                            li.html("<span class='label label-success'>"+data.titulo+"</span>");
                        }
                    }
                );
            });
        });
    </script>
@stop

Observação: Não vou ensinar Jquery por que esse tutorial é sobre Laravel.

Rota do Ajax

A essa altura do campeonato tá mais fácil fazer rotas novas do que ficar com preguiça as 6 da manhã embaixo do cobertor em um dia frio…

/*    checking tasks    */
Route::post('task/check', 'TaskController@check');

Controller Para o Check

O nosso controle precisa atuar desta forma:

  1. Verificar se é uma requisição AJAX
  2. Validar os dados enviados
  3. Procurar a task no banco de dados
  4. Atualizar a task

TaskController.php

    public function check() {
        //verifica se a request é ajax
        if (Request::ajax()) {
            //criando regras de validação
            $regras = array('task_id' => 'required|integer');

            $validacao = Validator::make(Input::all(), $regras);

            if ($validacao->fails()) {
                return Response::json( array("status" => FALSE) );
            }
            else {
                //tenta encontrar e atualizar a task
                try {
                    $task = Task::findOrFail(Input::get('task_id'));
                    $task->status = TRUE;
                    $task->save();

                    return Response::json( array("status" => TRUE, "titulo" => $task->titulo) );
                }
                //caso não tenha conseguido encontrar a task
                catch(Exception $e) {
                    return Response::json( array("status" => FALSE, "mensagem" => $e->getMessage()) );
                }
            }
        }
    }

Como estamos lidando com AJAX, quero retornar objetos JSON.
Para facilitar isso, o Laravel possui o Response::JSON, que recebe um array de dados, encapsula e envia como JSON para o cliente.

Para encontrar a Task desejada utilizo o método find do Eloquent, que recebe uma primary key e retorna um objeto Task.
Porém, nesse caso, como não posso garantir que o task_id passado pelo usuário é válido, estou utilizando o findOrFail, que funciona como o find mas levantando uma ModelNotFoundException caso não exista no banco de dados.

Assim, utilziamos AJAX, Jquery e Laravel para atualizar nossas tarefas.
Para isso foi necessário escrevermos 71 linhas de código.
MOLESA!!!!

OBSERVAÇÃO: Minhas explicações são assim, meia boca, por que é tudo muito intuitivo.
Em caso de dúvidas, utilize os comentários.

19 thoughts on “ToDoVel [Parte 11] Marcando as Tasks Como Concluídas

  1. Muito bom o post, estou indo um pouco devagar por causa do trabalho, mas já quero largar tudo e começar a usar logo o laravel, mas vamos com calma…

    Sei que é sobre laravel, mas no js não seria melhor usar um $(this).parents(‘li’) ao inves de dois parent() ?

    Esse js eu poderia jogar para um arquivo externo e apenas fazer a chamado dele ai ao inves de escrever um javascript no html?

    e só mais uma por enquanto, quando eu acesso para adicionar uma task perde o tema do bootstrap, sabe me dizer o pq?

    Valew

    1. Marcelo,
      sem pressa 😀
      Escrevi esses artigos bem devagar também, sempre que tinha um tempo livre.

      Quanto ao JS, seria melhor sim utilizar do seu jeito ao invés de dois parent().
      No dia que eu fiz isso, tava bugando, e minha paciência estava curta.
      Ai, na “força bruta”, fiz com dois parent()

      Você pode sim colocar tudo em um ou vários arquivos js.
      Só lembre-se de salvar os seus “assets” dentro da pasta public.

      Quanto ao seu problema, sei o que está acontecendo sim.
      Mas não vou dizer aqui!
      Isto é corrigido e ensinado no artigo 12 (o artigo depois desse).

      Boa sorte e bom aprendizado!

  2. Bom Galera, resolvi comentar aqui um pouco da experiencia q estou tendo.
    Também estou bem sem tempo, porem enjuado de programar sempre copiando e colando aqueles velhos códigos, criando aquele frankenstein. Foi ai que começou a busca por um framework, já conhecia o ZEND é um ótimo framework, mas não da para usar uma bazuca para matar uma formiga hehe ( assim q penso a respeito do zend ).
    Um amigo indicou o Laravel, e quando comecei a fazer os tutoriais, deu uma boa clareada, a parte de rotas achei meio semelhante ao SLIM framework, mas em fim, com certeza é muito fácil usar este Laravel.
    Boa iniciativa de compartilhar o seu conhecimento, didática muito boa, estou aprendendo bastante, vc ira influenciar muita gente.
    Abraço

  3. Então galera, no meu não funcionou neste capítulo, alguém poderia me ajudar?

    javascript executou até antes da função $.post, porque ….:

  4. Opa, o meu projeto também não estava funcionando neste capitulo. Fiquei trancado aqui por um bom tempo, pois não entendo muito de Jquery ainda, depois de vários testes consegui fazer funcionar.

    O que fiz: Removi a 1º barra de “/task/check”, para “task/check”, então funcionou normal.

    Alguém sabe me dizer porque no meu caso não funcionou com barra?

    1. Cara tenta ver se sua url base já não possui uma barra no final em app.php na pasta config.
      Tipo:

      ‘url’ => ‘http://localhost’,

      Se estiver assim: ‘url’ => ‘http://localhost/’,
      pode ser esse o problema. Mas é só suposição, já tive um problema parecido quando usava CodeIgniter … abçs a todos. Vlw Frenetic pelo conhecimento compartilhado em pt-br 🙂 sucesso pra vc cara.

  5. Deu certim aqui só tive que trocar isso : “/task/check”,
    por isso “task/check”,

    tô gostando d mais vlw pelo tutorial

  6. Para os que enfrentarem problemas com Javascripts não encontrados (Erro 500 quando inspecionado pelo Google Developer Tool) e erro de $ not defined ($ não definido), apenas volte no arquivo de exemplo do Bootstrap, veja o código fonte da página e salve todos os arquivos JS que estão na parte debaixo do HTML na pasta JS do projeto! 😀

  7. Guilherme, poucas vezes na vida fiz leituras tão prazerosas quanto essas, sua didática é ótima.
    Quanto ao Laravel, bom, estou saindo agora do CodeIgniter e estou encantado, só espero que eu possa usar HMVC, porque MVC puro é uma bagunça danada.
    EStou acompanhando fielmente essa série e até agora tudo na mais perfeita ordem.
    Tem um detalhe que eu não sei se perdi ou se vc ainda não fez:
    Consertar a URL do CSS e JS quando acessamos um método dentro do controller ( http://www.meusite.com/tasks/listar ). Eu resolvi por hora colocando a URL literal, no meu caso ‘http://localhost/pasta/’;
    Parabéns, e obrigado pela imensurável ajuda.

    1. Pode ser que eu tenha atropelado alguma parte.
      Acontece 🙁
      Porém, como eu falo nos artigos, eu disponibilizei o código fonte funcionando para o pessoal poder estudar.

      Obrigado pelo elogio.
      O objetivo foi ensinar de forma fácil.
      Boa sorte com o Laravel, ele é de se apaixonar.

  8. O meu esta dando erro!!! geralmente eu consigo acertar, mas desta vez não consegui. Pode me ajudar?

    Symfony \ Component \ HttpKernel \ Exception \ MethodNotAllowedHttpException
    Open: C:\xampp\htdocs\paginas\todovel\vendor\laravel\framework\src\Illuminate\Routing\RouteCollection.php
    * @param array $others
    * @return void
    *
    * @throws \Symfony\Component\HttpKernel\Exception\MethodNotAllowedHttpException
    */
    protected function methodNotAllowed(array $others)
    {
    throw new MethodNotAllowedHttpException($others);
    }

    Server/Request Data
    REDIRECT_MIBDIRS C:/xampp/php/extras/mibs
    REDIRECT_MYSQL_HOME \xampp\mysql\bin
    REDIRECT_OPENSSL_CONF C:/xampp/apache/bin/openssl.cnf
    REDIRECT_PHP_PEAR_SYSCONF_DIR \xampp\php
    REDIRECT_PHPRC \xampp\php
    REDIRECT_TMP \xampp\tmp
    REDIRECT_STATUS 200
    MIBDIRS C:/xampp/php/extras/mibs
    MYSQL_HOME \xampp\mysql\bin
    OPENSSL_CONF C:/xampp/apache/bin/openssl.cnf
    PHP_PEAR_SYSCONF_DIR \xampp\php
    PHPRC \xampp\php
    TMP \xampp\tmp
    HTTP_HOST localhost
    HTTP_CONNECTION keep-alive
    HTTP_CACHE_CONTROL max-age=0

  9. Quando eu acesso (http://localhost/paginas/todovel/public/task/check) esta ocorrendo o seguinte erro abaixo!!! Alguem pode me ajudar, ja refiz todo o tutorial até aqui, mas o erro continua!!!!

    ——————————–

    Symfony \ Component \ HttpKernel \ Exception \ MethodNotAllowedHttpException
    Open: C:\xampp\htdocs\paginas\todovel\vendor\laravel\framework\src\Illuminate\Routing\RouteCollection.php
    * @param array $others
    * @return void
    *
    * @throws \Symfony\Component\HttpKernel\Exception\MethodNotAllowedHttpException
    */
    protected function methodNotAllowed(array $others)
    {
    throw new MethodNotAllowedHttpException($others);
    }

    Server/Request Data
    REDIRECT_MIBDIRS C:/xampp/php/extras/mibs
    REDIRECT_MYSQL_HOME \xampp\mysql\bin
    REDIRECT_OPENSSL_CONF C:/xampp/apache/bin/openssl.cnf
    REDIRECT_PHP_PEAR_SYSCONF_DIR \xampp\php
    REDIRECT_PHPRC \xampp\php
    REDIRECT_TMP \xampp\tmp
    REDIRECT_STATUS 200
    MIBDIRS C:/xampp/php/extras/mibs
    MYSQL_HOME \xampp\mysql\bin
    OPENSSL_CONF C:/xampp/apache/bin/openssl.cnf
    PHP_PEAR_SYSCONF_DIR \xampp\php
    PHPRC \xampp\php

    1. Depois de muito queimar os miolos procurando pelo erro, descobri.

      troquei a Rota de

      Route::post(‘task/check’, ‘TaskController@check’);

      Para

      Route::any(‘task/check’, ‘TaskController@check’);

      Ou seja mudei de Post pata any e funcionou!

Deixe um comentário

O seu endereço de e-mail não será publicado. Campos obrigatórios são marcados com *