É possível criar uma ação "desfazer" usando esta estrutura atual do projeto?
É possível criar uma ação "desfazer" usando esta estrutura atual do projeto?
Pode dar um exemplo mais concreto?
Como no do gmail por exemplo, ao invés de confirma uma ação. ele permite realizar, mas depois você pode desfazer, como um ctrl + z no Windows por exemplo.
Mesmo que seja apenas no DOM, sem conexão com o banco (se for com conexão com o banco no exemplo do curso, melhor ainda).
Vou ter em mente o seu exemplo do gmail, ok?
Nunca precisei implementar isso, mas talvez um caminho seja usar o serviço $timeout
que é um wrapper para o setTimeout
do JavaScript. Mas você precisa ter um cuidado GIGANTE com ele, porque ele tem os mesmos problemas do setTimeout
. Sendo assim, veja que Angular é apenas um framework e que conhecer a linguagem JavaScript é fundamental para resolver problemas como esse.
Achei sua necessidade curiosa. Implementei uma solução como prova de conceito para te dar um norte a seguir (eu como usuário gostaria de ter esse recurso).
Eu alterei o projeto final do curso. No caso, coloquei a opção de desfazer para a remoção de fotos. Quando você clicar em remover, terá 3 segundos para desistir da operação. Mas isso é só prova de conceito, por exemplo, se o usuário realizar outra operação nesse tempo do desfazer? Ai você tem que decidir o que vai fazer.
Primeiro, segue a parcial principal.html
alterada para exibir o botão desfazer:
<div class="jumbotron">
<h1 class="text-center">Alurapic</h1>
</div>
<button ng-show="exibeBotaoDesfazer" class="btn btn-default" ng-click="desfazer()" >Desfazer</button>
<!-- código posterior omitido -->
Veja que o botão só é exibir se exibeBotaoDesfazer
em $scope
do controller for true. E quando o usuário clica em desfazer
ele realiza a operação. Agora, vamos para nosso controller.
// FotosController.js
/*
Veja que eu injeto o serviço `$timeout` para poder executar uma operação depois de tantos segundos.
*/
angular.module('alurapic').controller('FotosController', function($scope, recursoFoto, $timeout) {
$scope.fotos = [];
$scope.filtro = '';
$scope.mensagem = '';
recursoFoto.query(function(fotos) {
$scope.fotos = fotos;
}, function(erro) {
console.log(erro);
});
$scope.remover = function(foto) {
// quando remover é chamado, eu exibo o botão `desfazer` colocando true na propriedade abaixo:
$scope.exibeBotaoDesfazer = true;
// aqui que vem a malandragem. Eu digo que a remoção só será realizada depois de 3 segundos. Se antes desse tempo alguém clicar em desfazer, vai cancelar o envio do pedido de exclusão para o servidor.
// ATENÇÃO: EU GUARDO O RETORNO DE $timeout em uma propriedade do controller. É ela que me possibilita cancelar o timeout, pois tem uma referência para ele.
$scope.timeout = $timeout(function() {
recursoFoto.delete({fotoId: foto._id}, function() {
// Você concorda que se os 3 segundos acabam é porque meu código foi executado e como o tempo acabou eu não posso mais exibir o botão desfazer. Eu sumo bom o botão!
$scope.exibeBotaoDesfazer = false;
// aqui é o padrão
var indiceDaFoto = $scope.fotos.indexOf(foto);
$scope.fotos.splice(indiceDaFoto, 1);
$scope.mensagem = 'Foto ' + foto.titulo + ' removida com sucesso!';
}, function(erro) {
console.log(erro);
$scope.mensagem = 'Não foi possível apagar a foto ' + foto.titulo;
});
}, 3000); // veja que o $timeout recebe uma função e o segundo parâmetro o tempo em milisegundos
};
// aqui é nosso método que desfaz:
$scope.desfazer = function() {
// eu chamo o serviço $timeout.cancel que precisa receber uma referência do timer que criamos. Lembre-se que guardamos a referência em $scope.timeout
$timeout.cancel($scope.timeout);
$scope.mensage = 'Operação desfeita com sucesso';
$scope.exibeBotaoDesfazer = false;
}
});
O código funciona e pode ser uma luz nessa problemática que você quer resolver. Só não sei que pode ter algum efeito colateral mais sério. Até gostei de bolar essa solução :)
Show!!!! Por isso eu assinei o Alura! Vlw mesmo.
Vou implementar isso, e assim que o fizer, mando o link =D
Beleza, mas tipo, a coisa é mais complexa. Se o usuário clicar em desfazer em três fotos rapidamente? Do jeito que está, ele só conseguirá cancelar a última. Então tem que pensar a UX do cara direitinho.
Conseguindo implementar essa solução, me dá um feedback para a gente marcar esse post como resolvido.