Ir para conteúdo

POWERED BY:

Arquivado

Este tópico foi arquivado e está fechado para novas respostas.

aprendizhtm

Passar parâmetro de foreach(PHP) para carregar conteúdo via AJAX

Recommended Posts

Olá a todos!

 

Peguei alguns arquivos na internet para estudar e estou com alguma dificuldade em passar o valor de uma variável $msgID para uma url definida em um arquivo Javascript. Vou postar os códigos que obtive para ficar mais claro:

 

Eu tenho uma página principal que carrega outra página (caixa de entrada de mensagens), via Javascript. Na página de caixa de entrada, eu faço um foreach() em PHP para carregar uma tabela com todas as mensagens destinadas ao usuário:

<?php
foreach($msg_dados as $msg){
?>
<tr>
	<td>
		<input type="checkbox" class="mail-checkbox">
	</td>
	<td><?php echo $msgREMETENTE;?></td>
	<td><?php echo $msgASSUNTO;?></td>
	<td><?php $msgDATA;?></td>
</tr>
<?php
}
?>

Arquivos JS incluídos na página principal:

<script src="assets/plugins/jquery-1.10.1.min.js" type="text/javascript"></script>
<script src="assets/plugins/jquery-migrate-1.2.1.min.js" type="text/javascript"></script>
<script type="text/javascript" src="assets/scripts/inbox.js"></script>

Trecho do arquivo inbox.js:

    var loadMessage = function (el, name, resetMenu) {
        var url = 'msg_ler.php';

        loading.show();
        content.html('');
        toggleButton(el);
        
        $.ajax({
            type: "GET",
            cache: false,
            url: url,
            dataType: "html",
            success: function(res) 
            {
                toggleButton(el);

                if (resetMenu) {
                    $('.inbox-nav > li.active').removeClass('active');
                }
                $('.inbox-header > h1').text('View Message');

                loading.hide();
                content.html(res);
                App.fixContentHeight();
                App.initUniform();
            },
            error: function(xhr, ajaxOptions, thrownError)
            {
                toggleButton(el);
            },
            async: false
        });
    }

Cada linha da tabela (<tr>) é clicável, e eu queria redirecionar o usuário para uma página que, a partir da variável $msgID, carregasse a respectiva mensagem (ou seja, obter $msgID no arquivo msg_ler.php). Só que eu não tô sabendo fazer isso. Já pesquisei pela internet, tentei aplicar algumas dicas, mas nada deu certo e confesso que fiquei um pouco confuso. Talvez seja uma coisa simples, alguém poderia me dar alguma luz? Desde já, obrigado!

Compartilhar este post


Link para o post
Compartilhar em outros sites

Pesquisando bastante, consegui achar um link em inglês que quase resolveu o meu problema: http://www.daniweb.com/web-development/php/threads/459281/php-foreach-set-js-variable

Digo "quase" porque a dúvida do camarada é a mesma que a minha, aparentemente ele conseguiu resolver, mas... Minha "gonorância" (ou "cabeça quente" mesmo, porque já estou a horas batendo cabeça nisso) não me permitiram matar a charada.

Se eu escrever o valor na mão e pegar por GET vai, tipo

var url = 'msg_ler.php?msgID=3';

só que obviamente isso não rola. Já botei um "console.log(url);" pra ver o endereço na aba "console" do Chrome (última aba em "Inspecionar Elemento"), mas, enfim...

Obs: não havia achado que fosse relevante, mas percebi no final do arquivo inbox.js que a <tr> é clicável porque ela possui uma classe em CSS (".view-message", que não escrevi aqui porque achei que não tinha nada a ver... Putz). E o conteúdo (a página "msg_ler.php") é carregado dentro de uma <div> de classe "inbox-content":

return {
        //main function to initiate the module
        init: function () {

            // handle view message
            $('.inbox-content .view-message').live('click', function () {
                loadMessage($(this));
            });
    };

Vou continuar batendo cabeça aqui, mas agradeço a quem puder me dar uma luz. Valeu.

xxxxxxxxxxxxxxx Ponto de Mesclagem xxxxxxxxxxxxxxx

Reescrevi meus códigos, alguma coisa mudou, mas continuo precisando de uma ajudinha:

<?php
foreach($msg_dados as $msg){
?>
<tr>
	<td>
		<input type="checkbox" class="mail-checkbox">
	</td>
	<td><input class="inbox-messageId" type="hidden" value="<?php echo $msgID;?>" /><?php echo $msgREMETENTE;?></td>
	<td><?php echo $msgASSUNTO;?></td>
	<td><?php $msgDATA;?></td>
</tr>
<?php
}
?>

E o JS:

var loadMessage = function (el, name, resetMenu) {
	var messageId = $('.inbox-messageId').val();
        var url = 'msg_ler.php';

        loading.show();
        content.html('');
        toggleButton(el);

console.log(url);

		$.post(url, {id: messageId}, function (res) {
                if (resetMenu) {
                    $('.inbox-nav > li.active').removeClass('active');
                }
                $('.inbox-header > h1').text('View Message');

                loading.hide();
                content.html(res);
                App.fixContentHeight();
                App.initUniform();
        });
    }

Meu problema agora é que o JS sempre pega o primeiro valor do ID da tabela, e não o valor da célula em que eu clico (na qual coloquei um input hidden).

Alguém poderia me dar uma luz, ou algum administrador poderia mover este tópico para a seção de Javascript?


Compartilhar este post


Link para o post
Compartilhar em outros sites

Altere :

<?php
foreach($msg_dados as $msg){
?>
<tr>
	<td>
		<input type="checkbox" class="mail-checkbox">
	</td>
	<td><input class="inbox-messageId" type="hidden" value="<?php echo $msgID;?>" 
         onClick="visualiza('<?php echo $msgID;?>')" /><?php echo $msgREMETENTE;?></td>
	<td><?php echo $msgASSUNTO;?></td>
	<td><?php $msgDATA;?></td>
</tr>
<?php
}
?>

E no javascript a função vai ser chamada pelo método onClick:

 

<script>
visualiza(id){
   var url = 'msg_ler.php?msgID='+id;

    $("#ondevaisercarregado").load(url);

}
</script>

 

Outra forma mais parecida com o que vc tava fazendo:

 

O arquivo com o foreach php fica do jeito que vc fez:

<?php
foreach($msg_dados as $msg){
?>
<tr>
	<td>
		<input type="checkbox" class="mail-checkbox">
	</td>
	<td><input class="inbox-messageId" type="hidden" value="<?php echo $msgID;?>" /><?php echo $msgREMETENTE;?></td>
	<td><?php echo $msgASSUNTO;?></td>
	<td><?php $msgDATA;?></td>
</tr>
<?php
}
?>

Já o javascript com jquery fica assim:

 

<script type="text/javascript">
$(document).ready(function() {
       $("inbox-messageId").click(function(event) {
             var url = 'msg_ler.php?msgID='+ this.value;
             $("#ondevaisercarregado").load(url);
        });
});
</script>

Qualquer dúvida estamos aew!

Compartilhar este post


Link para o post
Compartilhar em outros sites

Obrigado, Edultra, mas infelizmente não deu certo, ou então eu não soube aplicar suas sugestões. Em ambos os casos, a div ficou "carregando" eternamente e o erro indicado pelo browser foi esse:

Uncaught ReferenceError: url is not defined

Vou postar todos os códigos de forma um pouco mais completa, talvez isso ajude a ter uma visão melhor do problema. Meu "inbox.js" (mais completo) ficou assim:

var Inbox = function () {

    var content = $('.inbox-content');
    var loading = $('.inbox-loading');

var loadMessage = function (el, name, resetMenu) {
       $("inbox-messageId").click(function(event) {
             var url = 'msg_ler.php?msgID='+ this.value;
             content.load(url);
        });

        loading.show();
        content.html('');
        toggleButton(el);

console.log(url);

		$.post(url, {id: messageId}, function (res) {
                if (resetMenu) {
                    $('.inbox-nav > li.active').removeClass('active');
                }
                $('.inbox-header > h1').text('View Message');

                loading.hide();
                content.html(res);
                App.fixContentHeight();
                App.initUniform();
        });
    }

    return {
        //main function to initiate the module
        init: function () {

            // handle view message
            $('.inbox-content .view-message').live('click', function () {
                loadMessage($(this));
            });

            //handle loading content based on URL parameter
            if (App.getURLParameter("a") === "view") {
                loadMessage();
            } else if (App.getURLParameter("a") === "compose") {
                loadCompose();
            } else {
               $('.inbox-nav > li.inbox > a').click();
            }

        }

    };

}();

A página principal (msg.php) possui os seguintes elementos:

	<div class="inbox-loading">Carregando...</div>
	<div class="inbox-content"></div>

[...]

	<script src="assets/scripts/inbox.js"></script>
	<script>
		jQuery(document).ready(function() {       
		   App.init();
		   Inbox.init();
		});
	</script>

Posto aqui a página msg_entrada.php "do jeito que estava", com o detalhe de que as "td's" possuem classe (coisa que eu, iniciante em javascript, havia ignorado e não publicado aqui antes):

foreach($resultado_msgENTRADA as $res_msgENTRADA){
		$msgID = $res_msgENTRADA['msgID'];
?>
	<tr>
	<td class="view-message" id="<?php echo $msgID;?>"><input class="inbox-messageId" type="hidden" id="<?php echo $msgID;?>" value="<?php echo $msgID;?>" /><?php echo $msgREMETENTE;?></td>
	</tr>
<?php
	}
?>

Concluí, portanto, que a <td> é clicável por causa da classe "view-message", e que talvez não fosse necessário colocar um input hidden em cada linha da tabela para transportar o ID para a outra página. Talvez eu pudesse usar o próprio elemento <td> para fazer isso... Eu tentei algumas coisas, como

var messageId = $('.view-message').attr(id);

mas, além de isso também só retornar o primeiro ID da tabela, existem outras colunas na página de mensagens que teriam a mesma ação que a do remetente (assunto da mensagem, data/hora). Ao serem clicadas, transportariam o ID da mensagem para a página "msg_ler.php" - e colocar o mesmo ID em todos esses TD's não deve ser boa prática. Mas, se eu usar "title", creio que o ID vai aparecer quando o usuário passar o mouse em cima, e isso também não me pareceu legal...

 

Por último: descobri que, usando ":eq()", poderia passar o ID que eu quisesse (eu só não sei é como colocar o ID que eu quero dentro do parêntesis)... Cheguei a ler um artigo sobre livequery, tive alguma dificuldade em usar (porque também não deu certo), mas também gostaria de crer que não preciso adicionar mais um plugin só pra fazer isso. Eu acho que a coisa deve ser bem mais simples do que eu imagino.

Compartilhar este post


Link para o post
Compartilhar em outros sites

Então fiz o teste aqui, e realmente o problema era o campo hidden, com ele ativo funciona, tive que mudar tambem para pegar pela classe:

 

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "xhtml11.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<script src="js/jquery-1.10.2.min.js" type="text/javascript"></script>
<script type="text/javascript">
$(document).ready(function() {

       $(".mail-checkbox").click(function(event) {
	   
			var url = 'msg_ler.php?msgID='+ this.value;
			$("#conteudo").load(url);
        });

});
</script>
</head>

<body>
	<table>
		<tr>
			<td>
				<input type="checkbox" class="mail-checkbox" value="1">
			</td>
			<td>Remetente bla</td>
			<td>assunto</td>
			<td>conteudo</td>
		</tr>
		<tr>
			<td>
				<input type="checkbox" class="mail-checkbox" value="2">
			</td>
			<td>Remetente bla</td>
			<td>assunto</td>
			<td>conteudo</td>
		</tr>
	</table>
<div id="conteudo">
conteudo
</div>
</body>
</html>

O exemplo acima esta funcional, testei aqui com um código php que imprimia na tela o id, lembre-se que vc tem que ter o jquery no caminho descrito no código acima.

 

Bem neste caso acima ele tem a checkbox, sem a checkbox com o evento funcionando no onclick na linha seria o seguinte:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "xhtml11.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<script src="js/jquery-1.10.2.min.js" type="text/javascript"></script>
<script type="text/javascript">
function visualiza(id){
			var url = 'msg_ler.php?msgID='+ id;
			$("#conteudo").load(url);
		}
</script>
</head>

<body>
	<table>
		<tr onClick="visualiza(1)">
			<td>Remetente bla</td>
			<td>assunto</td>
			<td>conteudo</td>
		</tr>
		<tr onClick="visualiza(2)">
			<td>Remetente bla</td>
			<td>assunto</td>
			<td>conteudo</td>
		</tr>
	</table>
<div id="conteudo">
conteudo
</div>
</body>
</html>

Os dois códigos estão funcionais.

Compartilhar este post


Link para o post
Compartilhar em outros sites

Eu havia copiado o seu código exatamente como está e o colado num arquivo HTML para testar aqui. Adicionei o Jquery como você disse, e... Não havia acontecido exatamente nada. Eu havia até ficado sem graça pra dizer isso, "poderia ser problema de versão do Jquery?", até que... Acrescentei um alert() e vi o retorno da url inteira. Lá, no alert, e não na <div>, o que me sugeriu que eu deveria acrescentar alguma coisa para exibir o retorno na referida div... Estou certo?

 

Bom, a ideia é pegar uma ID em uma página e transportá-la para outra (por GET ou por POST, pra mim tanto faz), porém vou mastigar um pouco mais esse seu norte para tentar chegar aonde quero, porque infelizmente a coisa ainda não funcionou por aqui.

 

O que estive reparando é que a <td> já é clicável (porque possui a classe CSS "view-message", referenciada em inbox.js), portanto o código original do arquivo inbox.js já possui uma espécie de "método onclick", se é que posso chamar isso assim. Veja:

  // handle view message
  $('.inbox-content .view-message').live('click', function () {
      loadMessage($(this));
  });

Creio que é este trecho acima que torna a <td> clicável e dá retorno na "div inbox-content" (o retorno, por enquanto, é o carregamento da página msg_ler.php sem o ID desejado). Mesmo assim, coloquei a função "visualiza" no onclick da <td> e acrescentei o código dessa função dentro de "var loadMessage" (porque se eu botar fora aí é que não vai mesmo), e dessa vez o browser acusou dois erros:

Uncaught ReferenceError: visualiza is not defined
Uncaught ReferenceError: url is not defined 

E o conteúdo, novamente, não carrega. Vou continuar tentando! :thumbsup:

Compartilhar este post


Link para o post
Compartilhar em outros sites

Experimente isolar os componentes. O Edultra disse no post #5 que aqueles códigos funcionam.

 

Então remova todas as outras funcionalidades, como esses App.init() e Inbox.init(), e teste. Se ele testou e funcionou, com você tem de funcionar também, é lógica.

 

Daí você vai adicionando os outros recursos um a um. Põe o ícone/texto de loading, as instruções de console (que eu acho perigoso sem uma condição entre modo desenvolvimento, modo produção), e por último as "classes" que você inicializava.

 

Quando parar de funcionar, se parar, você vê quem é o culpado.

Compartilhar este post


Link para o post
Compartilhar em outros sites

Já havia tentado isso também, isolar componentes para arejar e visualizar melhor a coisa. Tentando outras coisas, o mais perto que consegui chegar foi isso:

var messageId = $('.view-message').click(function() {
        alert($(this).attr('id'));
});

Na primeira "clicada" no <td>, nada acontece. Na segunda "clicada", o meu alert() até mostra o ID, mas aparece duas vezes. Na terceira, mostra o ID três vezes, e assim por diante. Cheguei perto, mas ainda não está funcionando.

Compartilhar este post


Link para o post
Compartilhar em outros sites

Já que o console parece não estar ajudando em nada, rode a página com o Painel de Rede do Firebug (Firefox) ou o Network Monitor do Chrome aberto e veja o que você está recebendo como resposta.

 

De repente, alguma má configuração no seu servidor pode, quem sabe, estar retornando um erro de servidor (502 é o mais comum), ou se a URL estiver de alguma forma mal formada, um 404. Se houver alguma autenticação, um 403 e etc.

Compartilhar este post


Link para o post
Compartilhar em outros sites

Então, as coisas estavam corridas por aqui e só hoje deu tempo pra dar uma olhada, como falei o código realmente esta funcional:

 

http://www.developersbr.com.br/testes/testeajax.php

 

Faça primeiramente o que o bruno faleu, retire os outros .js que vc inseriu, utilize o Firebug, o console para verificar erros, eu particularmente quando não consigo encontrar nada utilizo o complemento webdeveloper, no canto superior direito ele tem 3 itens onde indicam erros, javascript, css etc.

Compartilhar este post


Link para o post
Compartilhar em outros sites

Fiz tudo o que me disseram, adicionei também o Webdeveloper (também não conhecia) e... Nada.

 

Obs: existem coisas que eu não posso remover, senão aí é que a coisa não funciona mesmo. Uma delas, por exemplo, é o Inbox.init(), porque é justamente essa linha que "dispara" tudo. Basta eu comentá-la para não abrir nada dentro da <div> ".inbox-content".

 

Edultra, seu código funcionou perfeitamente online, mas bastou eu copiá-lo para rodar localmente que nada funcionou. Nenhum erro ou warning do Webdeveloper (três ticks verdes). Apesar de ser só javascript, rodei dentro e fora do Wampserver (Windows 8 e XP).

Compartilhar este post


Link para o post
Compartilhar em outros sites

Certo... Se não deu nenhum erro de servidor a requisição AJAX está funcionando. Agora ainda com o painel aberto, carregue a página, espere a requisição para aquele URL ser feita e, no painel, clique no link daquela requisição.

 

Eu não lembro como Firebug mostra, mas o Chrome mostra três opções: Headers, Preview e Response. O primeiro são os cabeçalhos recebidos, o segundo é o que a página ecoou de volta pro cliente e o terceiro é o HTML desse preview.

 

Na correspondência do Firebug, veja se o HTML que o servidor está retornando está compatível com o que o seu JS está fazendo.

 

Há um tempo atrás eu já tive problemas nesse sentido. Eu ecoava algo lá no PHP, navegava pelos nós no JS, mas se errava alguma coisinha, um nó a mais ou a menos, o resultado era diferente do que eu esperava.

 

Por exemplo. Você parece estar se baseando em elementos com a classe .view-message. Veja se o HTML que está sendo retornado possui essa classe, ou se as tags estão bem formadas (acontece muito no abre e fecha de tags PHP) e etc.

 

Se tudo o mais falhar, infelizmente você vai ter mesmo que remover essas "classes" ou então suprimir algumas coisas delas pra isolar o problema.

Compartilhar este post


Link para o post
Compartilhar em outros sites

Estou isolando componentes como me sugeriu, essa tá mesmo bem complicada. Mas é bom, assim eu ganho experiência. Meu último progresso:

var loadMessage = function (el, name, resetMenu) {
	var url = 'toks/toks_ler.php';

	el.click(function(){
		var teste = this.id;
		alert(teste);
		return false;
	});
}

Esse "el" era passado pela função o tempo todo, se eu der um "alert()" nele o retorno é "[object Object]". Aí eu tive a bendita ideia de "usá-lo" numa função. A coisa melhorou, mas ainda não está 100%.

 

Se eu clicar uma vez em alguma linha da tabela, nada acontece; mas, a partir da segunda clicada, o "alert()" mostra o que eu quero, e uma vez só (graças ao "return false"). Isso acontece com todas as linhas da tabela (é como se, para eu obter o resultado esperado, eu tivesse que clicar em todas as linhas da tabela uma vez).

 

Eu tentei visualizar o que está acontecendo pelas ferramentas sugeridas por vocês, mas não vejo nada. Pelo comportamento da coisa até esse ponto, dá pra sugerir alguma coisa?

 

Creio que estou quase lá, falta pouco!

Compartilhar este post


Link para o post
Compartilhar em outros sites

Imagino que ao invés de:

this.id

Deva ser:

$( this ).attr( 'id' )

Porque dessa forma você resolve o escopo do this para o nó que foi clicado.

Compartilhar este post


Link para o post
Compartilhar em outros sites

Bom, eu mantive o código como estava, e só troquei a linha que você sugeriu. O resultado (comportamento) foi exatamente o mesmo.

 

Se não me engano, entre as dúzias e dúzias de artigos e posts de fóruns que já li até agora (a maioria em inglês), alguém comentou que essas duas formas seriam equivalentes.

Compartilhar este post


Link para o post
Compartilhar em outros sites

ACABOOOOOOOOOOUUUUUU!!!!!!!!!!!!!

    var loadMessage = function (el, name, resetMenu) {
        var url = 'msg_ler.php';
	var messageId = el.attr('id');

        $.post(url, {id: messageId}, function (res) {
                if (resetMenu) {
                    $('.inbox-nav > li.active').removeClass('active');
                }
                $('.inbox-header > h1').text('View Message');
                loading.hide();
                content.html(res);
                App.fixContentHeight();
                App.initUniform();
        });
    }

Eu sabia que essa solução tinha que ser simples, era basicamente uma linha só!!!

	var messageId = el.attr('id');

Caramba, já passa de meia-noite, eu realmente queimei MUITO pra matar essa charada. Que bom que terminou! :joia:

 

Meus sinceros agradecimentos a vocês, Edultra e Bruno, pois me deram dicas valiosas. Sem vocês, creio que não teria conseguido! Valeu!!! :clap:

Compartilhar este post


Link para o post
Compartilhar em outros sites

Acabou que todo o seu problema era justamente o que disse no post #15, a resolução do escopo do this.

 

Quando você invoca a função loadMessage(), você já estava resolvendo ele para o objeto jQuery através de $( this ), foi falta de atenção minha não ter visto isso lá no post #2.

 

Uma vez que você já tem um objeto jQuery, não precisava resolver mais nada e usar os métodos do objeto jQuery normalmente.

Compartilhar este post


Link para o post
Compartilhar em outros sites

×

Informação importante

Ao usar o fórum, você concorda com nossos Termos e condições.