Javascript dependente de JQuery em template twig

309 views
Skip to first unread message

Alan Candido

unread,
Jul 22, 2014, 4:21:57 AM7/22/14
to symfo...@googlegroups.com
Ola Pessoal,

Tenho o template (trecho):
{% extends '::base.html.twig' %}

{% block leftSide %}
    <div class="btn-group btn-group-vertical">
        {{ render(controller('MeuBundle:MeuController:selection', {'id': id })) }}
    </div>
.....
{% endblock %}

O template de MeuBundle:MeuController:selection é (trecho):

<div class="dropdown">
        <button class="btn btn btn-info dropdown-toggle" type="button" data-toggle="dropdown">Cliente
            <span class="caret"></span> <span class="sr-only">Clientes</span>
        </button>
        <ul role="menu" class="dropdown-menu">
...
</div>
....
<script type="text/javascript">
$(function() {
console.debug("iniciando javascript");
...
}

Ao executar, obtenho erro de execução de javascript "ReferenceError: $ is not defined" e isso acontece porque o JQuery ainda não foi carregado (este é carregado no final do ::base.html.twig).

Colocando a carga do JQuery no inicio do template base funciona, porém isso não é considerado boa prática.

Alguma ideia de como resolver o problema, mantendo a carga do JQuery no final da página.

--
Boa Sorte e a Paz do Senhor,
Good Luck and Peace of the Lord

[:>} Alan Cândido ><>
Analista de Pesquisa e Desenvolvimento
Analyst Research and Development

Acompanhe dicas e outras informações em
Follow tips and other information on (only portuguese)
http://paradesenvolvedores.blogspot.com/
http://albb.cjb.net/

mari...@gmail.com

unread,
Jul 22, 2014, 7:10:27 AM7/22/14
to symfo...@googlegroups.com
Você precisa colocar o seu código JavaScript dentro do "block" de JavaScript

{% block javascripts %}
    {{ parent() }}
    <script type="text/javascript">
        $(function() {
            console.debug("iniciando javascript");
        }
    </script>
{% endblock %}

Dessa forma o seu código JavaScript será inserido dentro do "block" de JavaScript do "base.html.twig".
Atenção para a funcção "parent()", ela é importante caso você não queira subscrever algum JavaScript que já existe no "base.html.twig".

Abraço,


Mario Rezende
11-99339.4805 | about.me/mariorez


--
You received this message because you are subscribed to the Google Groups "Symfony Brasil" group.
To unsubscribe from this group and stop receiving emails from it, send an email to symfony-pt+...@googlegroups.com.
To post to this group, send email to symfo...@googlegroups.com.
Visit this group at http://groups.google.com/group/symfony-pt.
For more options, visit https://groups.google.com/d/optout.

Cassiano Tartari

unread,
Jul 22, 2014, 7:17:18 AM7/22/14
to symfony-pt
Bom dia.

  Ano passado pesquisei um pouco sobre o carregamento de scripts js no final da página. Em alguns casos existem problemas, principalmente nos scripts que escrevem algo no html, se não me engano um dos métodos que tinha problema é o "append", isso tudo, claro, na maioria das vezes é com o nosso querido IE. Lembro que li sobre como carregar o js inline somente depois de carregar toda a página, mas pra te ser sincero não lembro qual foi a solução e se teve solução sei que nesse projeto que tive problemas com JS os scripts estão começando assim: jQuery(function() {

   Outra coisa que lembro ter lido é que tu pode adicionar a tag defer <script src="..." type="text/javascript" defer="defer"></script> que garante que o JS será executado somente após a página ter sido renderizada.

Cassiano Valle Tartari
MSc. Computer Engineer

Tel: +55.48.84474818
Email: fal...@cassianotartari.eng.br
Site: http://www.cassianotartari.eng.br

QR Code


--

Leonn Leite

unread,
Jul 22, 2014, 7:43:56 AM7/22/14
to symfo...@googlegroups.com
Amigo,

poderia copiar a parte do base.html.twig que fala de javascript?

Acontece que você está efetuando a chamada de JS antes de instanciar o jQuery.


Atenciosamente,
Leonn Leite

Alan Candido

unread,
Jul 22, 2014, 7:31:04 PM7/22/14
to symfo...@googlegroups.com
Ola Pessoal,

@Mario Rezende,

Pelos testes que fiz, o comando "block" é ignorado quando chamamos a função render a partir de outro template.
Isso até faz sentido, pois a ideia de renderizar o template desta forma é ter flexibilidade no uso deste.

@Cassiano,
Pelo que sei (e confirmado com algumas pesquisas) o "defer" causa a execução do script em paralelo com a renderização e não ao final.
E neste caso, não resolve usar a execução em paralelo.

O uso de jquery no lugar do $, também não resolve, pois o jquery ainda não foi carregado.

@Leon,

Grato pela informação. Eu já sei que o problema é que de ordem de carga/execução.
Como disse no inicio, se colocar a carga dos scripts no começo a execução ocorre sem problemas.
Como comentei com o Mario, o block é ignorado e por isso o meu JS é executado assim que é carregado (ele não é inserido no bloco de scripts definido no base.html.twig). Segue abaixo (editado devido ao tamanho) com blocks em destaque:

<!DOCTYPE html>
<html lang="pt-br">
<head>
<meta charset="utf-8">
.....
<title>{% block title %}Bem Vindo!{% endblock %}</title>
....
{% block stylesheets %}{% endblock %}

</head>

<body>
    <div id="wrapper">
        <!-- Topbar -->
....
        <div id="page-wrapper" class="container">
        {% block content %}{% endblock %}
        </div>
    </div>

<!-- JavaScript -->
    <script type="text/javascript" src="{{ asset("js/jquery-1.10.2.js") }}"></script>
.....
    <!-- Page Specific JavaScript -->
    {% block javascripts %}{% endblock %}
</body>
</html>



Agradeço a todos pela atenção.

Yuri Gauer Marques

unread,
Jul 23, 2014, 2:11:39 PM7/23/14
to symfo...@googlegroups.com
tipo, nao entendi se vc ja resolveu ou nao o problema, mas fazemos da seguinte forma no base.html a gente fez algo assim
<!-- JavaScript -->

   
.....
    <!-- Page Specific JavaScript -->
   
{% block javascripts %}
            
<script type="text/javascript" src="{{ asset("js/jquery-1.10.2.js") }}"></script>(coloca a declaração do jquery dentro do block javascript)
    {% endblock %}




posteriormente no view que vamos usar o recurso do jquery vc declara no final da seguinte forma (colei do mariorez)
vies.html.twig
{% block javascripts %}
    {{ parent() }} (função que faz receber o conteudo do block sem sobrescrever o original)
    <script type="text/javascript">
        $(function() {
            console.debug("iniciando javascript");
        }
    </script>
{% endblock %}


dessa forma o block javascript vai herdar o conteudo do block da base e vai adicionar o seu comando em seguinda, e assim não vai ignorar o conteudo do block javascripts, mas tem q por o {{ parent() }}
Yuri Gauer Marques
Bacharel em Ciência da Computação - UFMT
(65)8115-1899

Leonn Leite

unread,
Jul 23, 2014, 2:18:30 PM7/23/14
to symfo...@googlegroups.com
Opa Yuri,
não conhecia o {{ parent() }}, bacana a informação.


mas é bem isso mesmo. Se você não quiser mudar seu base.html.twig:

o arquivo qualquer.html.twig, seria:

{% block javascripts %}
    <script type="text/javascript">
        $(function() {
            console.debug("iniciando javascript");
        }
    </script>
{% endblock %}

Atenciosamente,
Leonn Leite

Alan Candido

unread,
Jul 25, 2014, 12:55:13 AM7/25/14
to symfo...@googlegroups.com
Ola Yuri,

Grato pela resposta, mas como já comentei, a marcação block/endblock é ignorada quando usamos a função render().




Em 23 de julho de 2014 15:11, Yuri Gauer Marques <yurigm...@gmail.com> escreveu:

Marcelo Rodrigues

unread,
Jul 25, 2014, 9:01:24 AM7/25/14
to symfo...@googlegroups.com
Alan, 

Pergunta.: existe alguma razão especial para o javascript ter de estar no template MeuController::selection? Ele vai usar alguma variável ou valor vindo do controller? 

Senão, uma outra solução, talvez, seja você separar o template do javascript e incluí-lo com um render ou include. Ex: 

{% block leftSide %}
    <div class="btn-group btn-group-vertical">
        {{ render(controller('MeuBundle:MeuController:selection', {'id': id })) }}
    </div>
{% endblock %}

{% block javascripts %}
  {{ parent() }}
  {{ include "MeuBundle:MeuController:selectionJavascript.html.twig" }}
{% endblock %}

Ou ainda, se não houver uso de valores vindo de controller, separar o javascript em um arquivo "js" estático mesmo. 

Apenas para explicar melhor aos colegas, quando se usa o "render" ou "include", o contexto do template "incluído" não é o mesmo do template do que o está incluindo, dessa forma, ele perde a referência em relação aos blocos definidos posteriormente em templates "pais". 

Marcelo
Marcelo Rodrigues

Analista Desenvolvedor Web
Zend Certified Engineer ZEND018059

+55 (61) 9273 2058

Rafael Goulart

unread,
Jul 25, 2014, 9:33:04 AM7/25/14
to symfo...@googlegroups.com
Meus dois centavos.

Apesar de, obviamente, ser possível utilizar o {{ parent() }}, eu prefiro uma abordagem mais simples: crio dois blocos, um para os javascripts "globais" e outro vazio para possíveis inclusões:

{% block global_javascripts %}
    {# ... todos javascripts globaisutilizados ou via assetic #}
{% endblock global_javascripts %}

{% block javascripts %}{% endblock javascripts %}

Deste modo qualquer programador que incluir não comete equívocos, e pode também sobrescrever os JS globais se necessário.

Um exemplo de layout com esta abordagem, inclusive para CSS e outros JS no <head> (não indicado, mas eventualmente necessário):


Em tempo: na minha visão, <script> local no template só tem sentido se você passa alguma variável com informações vindas do controller (exemplo: labels para colunas de um datatables). Mesmo assim, é sempre melhor trabalhar de modo a ter JS isolados, que podem ser concatenados e incluídos via assetic.

[]'s
Rafael Goulart
Reply all
Reply to author
Forward
0 new messages