none
Problema Ajax.beginForm UpdateTargetId

    Question

  • Olá para todos.

    Eu implementei um form utilizando o Ajax.Begin form, porém estou com um problema:

    Eu tenho uma tabela, onde cada célula da tabela possui um formulário, sendo do tipo ajax.beginform. Ao dar submit, a célula inteira é atualizada.

    Dentro de cada formulário eu tenho 3 inputs(type="Text") onde eu utilizo o plugin meioMask para criar máscara decimal.

    Ao carregar a página a máscara funciona perfeitamente, porém ao dar submit, os inputs perdem a máscara.

    Alguém tem idéia de como resolver o problema?

    Obrigado a todos.

    Wednesday, March 31, 2010 7:46 PM

Answers

  • Fala mkoka blz?

    Olha não tem problema o id do botão ser dinamico, voce pode utilizar o seletor jQuery apontando pra uma classe css, então desta maneira basta indicar a classe em seu botão dinamico.

    Exemplo: //seu seletor $('.classe_btn')

    Como ficaria a implementação :

           $(".classe_btn").click(function() {
                $.ajax({
                    type: "POST",
                    url: "/Nome_do_Controller/Sua_Action",
                    success: function(data) {
                        $("#divResultado").html(data);
                        $("input:text").trigger("applymask");
                    },
                    error: function(XMLHttpRequest, textStatus) {
                        alert(textStatus);
                    }
                });
            });

           //Seu botão, pode ser um tipo button já que voce irá utilizar ajax

          <inputtype='button'class='classe_btn' id='<%=String.Format("Botao{0}", ViewData("Celula"))%>'      value="salvar"style="display:none;"/>

    Olhei seu exemplo, e esta um pouco confuso mesmo, segue algumas dicas. 

    A parte de renderizar seu form não é necessário utilizar uma RenderAction, voce pode utilizar o RenderPartial, e seu form pode ser um ascx, dessa maneira não será necessário criar uma action especifica. Vi tambem que voce utilizou o "getElementById", blz mas já que voce esta utilizando e carregando o jQuery devido a máscara dos campos, pode utilizar o jQuery tambem para selecionar seus elementos, aos invés de usar "getElemenById('seu_id')", use "$('#seu_id')" que é mais simples de codificar. Posta os resultados depois.

    Eu recentemente li um livro dos cabeças do MVC, e eles disponibilizaram a primeira parte com mais de 100 páginas gratuitamente, ensinam a utilizar melhores práticas e reutilização de código, uso do membership, de uma olhadinha no endereço abaixo para donwload que vale muito apena.

    http://www.wrox.com/WileyCDA/Section/id-321793.html

     

    Thursday, April 15, 2010 10:12 PM

All replies

  • Olá,

    Você pode configurar o callback das solicitação , dentro do AjaxOption você só precisa configurar o OnSuccess e setar a mask novamente, neste link tem exemplos de como você pode fazer isso

    http://www.danielfonsecacastro.com.br/post/2009/05/26/Entendendo-a-classe-AjaxOptions.aspx


    Abraços,
    Daniel Fonseca Castro
    www.danielfonsecacastro.com.br
    Thursday, April 01, 2010 12:42 AM
  • Olá Daniel, tudo bem? Será que você pode me dar uma ajudinha?

    eu não sei muito ajax, jquery,etc..

    está assim minha aplicação:

        <script type="text/javascript" >
            (function($) {
                $(function() {
                    $('input:text').setMask({ mask: '99,999', type: 'reverse', defaultValue: '000', autoTab: false });
                }
            );
            })(jQuery);
        </script>

    pelo que entendi, você disse para eu configurar no OnComplete(funcionará tanto para sucess ou Failure) para reexecutar o jquery. Mas como eu faria isso?

    Obrigado.

    Thursday, April 01, 2010 1:36 PM
  • Olá mkoka,

    Tudo em paz!

    Você precisa configurar o AjaxOption, por exemplo

     

    <% using (Ajax.BeginForm("ActionName","ControllerName",new AjaxOptions(){UpdateTargetId = "retorno", 
    OnComplete = "Complete"})) {%>
            
            inputs....
           
    <%} %>
    

     

    E definir o método Complete

     

    <script type="text/javascript" >
        function Complete(request, ajaxOptions, ajaxContext) {
            $('#ID_DO_INPUT_QUE_PERDEU_A_MASK').setMask({ mask: '99,999', type: 'reverse', defaultValue: '000', autoTab: false });
        }
    </script>
    
    Só uma observação o OnComplete é executado somente quando a solicitação é executada com sucesso (sem erros), quando ocorre algum erro o OnFailure será executado se você precisar dele você tem que configura-lo.

     

     

     

     

     


    Abraços,
    Daniel Fonseca Castro
    www.danielfonsecacastro.com.br
    Thursday, April 01, 2010 1:57 PM
  • Não consegui fazer funcionar Daniel. Eu fiz uns testes, e o JS Complete é executado porém a máscara não funciona.

    Tem idéia do que possa ser?

     

    De forma resumida, eu tenho algo assim:

    <div id="atualizar>

    <% PartialView() %>

    <\div>

     

    PartialView:


    ajax.BeginForm(updateTargetId = "atualizar')

    Deu pra entender como está?

     

     

    Na partialView que é atualizada, eu coloquei um script simples do tipo...

    <script>
        alert('asdasdasdasdasd');
    </script>

     

    Só na hora de carregar a página que aparecem os alert´s. Com o UpdateTargetId não aparece mais.

    Thursday, April 01, 2010 2:23 PM
  • Olá Mkoka,

    O OnComplete esta funcionando sempre? Passa o javacript também e os erros caso exista algum.


    Abraços,
    Daniel Fonseca Castro
    www.danielfonsecacastro.com.br
    Thursday, April 01, 2010 6:37 PM
  • bom, o javascript foi o que vc me forneceu. Não acusa nenhum erro, só não cria a máscara.

    Fica complicado eu postar o código pq é grande demais. Mas se mesmo assim quiser, eu posto.

    Obrigado pela atenção.

    Thursday, April 01, 2010 7:06 PM
  • Olá mkoka,

    Se você não encontrar a solução, você pode zipar os códigos colocar em algum lugar (por exemplo skydrive) e passar o link.


    Abraços,
    Daniel Fonseca Castro
    www.danielfonsecacastro.com.br
    Friday, April 02, 2010 11:01 AM
  • Olá Daniel, desculpe a demora pra responder. Eu ainda não consegui resolver o problema, mas fiz um tratamento de erro para contornar o problema. Vou fazer uns testes aqui. Será que, caso seja possível, eu executar o javascript quando criar a partialView resolveria? E seria certo?
    Monday, April 05, 2010 12:12 PM
  • Olá Mkoka,

    Sim resolveria foi exatamente isso que eu sugeri na primeira resposta note que OnSuccess e uma função do tipo Callback, ela é executada toda vez que você retorna a sua partial view com sucesso é exatamente neste momento que você deve setar a mask para os inputs que estão retornando na partial view.

     


    Abraços,
    Daniel Fonseca Castro
    www.danielfonsecacastro.com.br
    Tuesday, April 06, 2010 11:00 AM
  • Olá, Tudo bem mkoka?

    Pelo que notei, voce esta perdendo a máscara de seu campo quando é retornada uma partialview, correto?

    Isso acontece por que qualquer elemento que tenha sido gerado dinâmicamente seja por ajax ou mesmo javascript sem requisições assincronas, este não será acessivel pelo script já existente em sua página.Para contornar isso voce poderia usar o manipuladores de eventos live ou delegate do jquery, que te possibilita acessar elemento dinâmicos em sua página.

    'obs: delegate disponível a partir da versão 1.4.2 do jquery'

    Como o Daniel citou, voce poderia informar um callback para ser executado no OnSuccess do Ajax.beginForm, exemplo para o nome do seu callback "apply".Neste "apply" voce poderia disparar um evento personalizado utilizando o método live ou delegate e setar a máscara em seus campos.

    Segue como ficaria a implmentação:

    //No carregamento padrão do jQuery

    $(function() {


                //Cria o um evento personalizado chamado applymask e anexa o a todos os seus 'input:text'
                $("body").delegate("input:text", "applymask", function() {

                  //Seta sua máscara
                   $(this).setMask({ mask: '99,999', type: 'reverse', defaultValue: '000', autoTab: false });

                });


               //dispara inicialmente seu evento para os 'input:text' já existentes na página

              $("input:text").trigger("applymask");
            });

    //Em seu Ajax.beginForm apontar para a função abaixo, {OnSuccess="apply"}

    function apply()

    {

      $("input:text").trigger("applymask");

    }

    Realizei o teste aqui navegando em elementos dinamicos e funcionou corretamente, mas como isso pode variar de caso a caso, realize um teste e nos diga se deu certo.

    Para mais detalhes sobre os manipuladores de evento dinâmicos, de uma olhada aqui : http://api.jquery.com/delegate/

    e aqui : http://api.jquery.com/live/

     

    Já em relação ao alert que voce diz não ser executado a partir de sua partial carregada dinâmicamente, tente o seguinte:

    //Executa a si mesma quando carregar sua partial

    (function(){

      alert("alert que não funcionou no UpdateTargetId")

    })();

     

     

    • Proposed as answer by _Willian_ Wednesday, April 07, 2010 1:22 AM
    Wednesday, April 07, 2010 1:19 AM
  • Wilian eu fiz exatamente o que vc falou, porém está dando o seguinte erro:

    Microsoft JScript runtime error: 'b' is null or not an object

    "//Em seu Ajax.beginForm apontar para a função abaixo, {OnSuccess="apply"}"

    Eu havia deixado com "()" e deu o erro, porém se eu tirar, não dá mais o erro, mas a máscara também não funciona.

    Esse erro aconteceu no MicrosoftAjax.js

    Como eu sou totalmente novato em Ajax e Jquery, não tenho idéia do que possa ser.

    tem idéia?

    Friday, April 09, 2010 6:16 PM
  • Fala mkoka,

    Então cara o erro aconteceu possivelmente porque você passou a chamada da sua função, mas o correto é passar apenas uma referência ou passar uma função anônima que será encapsulada e executada no momento que o evento OnSuccess for disparado.

    Exemplos:

      //passando uma referência

      OnSuccess="apply"

      //passando uma função anônima que executa sua função

      OnSuccess="function(){

         apply();

      }"

    Mas a questão é que não funcionou a máscara, hm poste em algum lugar o seu código ou exemplo bem próximo  dele como o Daniel citou, para que a gente possa analisar melhor.

    Em todo caso vou criar uma situação aqui mais semelhante com a que vc postou anteriormente. Assim que eu conseguir algo posto de novo, valew?

    Até breve.

    Saturday, April 10, 2010 7:07 PM
  •  

    Fala mkoka,

    Olha dei uma pesquisada aqui e fiz mais testes, e é estranho a mascará não funcionar quando voce passa uma referencia a função apply.

    Aqui realizei o teste da forma mais próxima da que imagino que esteja em seu código, carregando a partialview com novos inputs e com um javascript embutido similar ao alert que voce citou ter na partial, blz, funcionou a mascara mas não o javascript embutido.

    Em relação ao scriptnão executar, o que acontece é que a partial(html) não é avaliada pelas funções internas do MicrosoftAjax, desta maneira seu script nunca será executado a menos que voce retorne um JavaScriptResult, porem como voce quer retornar um html+javascript, pode usar seu form com a função ajax do jQuery, que alem de avaliar o retorno do servidor, tambem setará sua mascara para os inputs.

    //Segue a implementação, que testei

            $("#id_do_botao_enviar").click(function() {
                $.ajax({
                    type: "POST",
                    url: "/Nome_do_Controller/Sua_Action",
                    success: function(data) {
                        $("#divResultado").html(data);
                        $("input:text").trigger("applymask");
                    },
                    error: function(XMLHttpRequest, textStatus) {
                        alert(textStatus);
                    }
                });
            });

     

    Note que no parametro url passei o nome do "controller/sua action", então será necessário modificar apenas seu form que não será mais um Ajax.BeginForm e sim Html.BeginForm, com isso vc poderá setar a máscara e jogar a partial avaliada na div divResultado.

    Para enviar os dados do formulario voce deve utilizar o parametro "data" após o "url" por exemplo, de uma pesquisada aqui para referência -> http://api.jquery.com/jQuery.ajax/

    Bom é isso, aqui funcionou certinho,  qualquer duvida posta ai.

    Sunday, April 11, 2010 4:32 PM
  • Bom dia Wilian, vou tentar fazer as modificações que você me indicou.

    Acho que meu exemplo seria algo parecido com o código abaixo:

     

    //PartialView: contém os input que precisam do mask

    <%="" %>
    <%  Using (Ajax.BeginForm("NomeDoAction", "NomeDoController", New With {.celula = ViewData("Celula")}, New AjaxOptions With {.UpdateTargetId = String.Format("Configuracao{0}", ViewData("Celula"))}, New With {.name = String.Format("Formulario{0}", Model.ItemColorido.Id)}))%>
    <table style="font-size: 10px;">   
            <tr style="margin: 1px; padding: 1px;">
                <td>
                    <%=Html.Hidden("IdColorido", Model.ItemColorido.Id)%>
                </td>
                <td>
                    <%=Html.CheckBox("AtivoColorido", Model.ItemColorido.Ativo, New With {.onClick = "document.getElementById('"& String.Format("Botao{0}", ViewData("Celula")) &"').click();"})%>
                </td>
                <td>
                    <%=Html.Encode("Colorida")%>
                </td>
                <td>
                    R$
                </td>
                <td>
                    <%=Html.TextBox("ValorColorido", Model.ValorItemColorido, New With {.style = "width:45px;", .maxlength = "6", .name = "Valor", .onChange="document.getElementById('"& String.Format("Botao{0}", ViewData("Celula")) &"').click();"})%>
                </td>
            </tr>
    </table>
        <center>
            <input type='submit' id='<%=String.Format("Botao{0}", ViewData("Celula"))%>' value="salvar" style="display:none;"/>
        </center>
    <%End Using%>

    //View que chama a partial

    <table border="2" id="TabelaGeral">
            <tr>
                <th style="width:100px; text-align:center">
                    Tamanho
                </th>
                <% For Each papel As Nucleo.TipoPapel In Model.ListaPapel%>
                    <th style="text-align:center">
                        <%=Html.Encode(papel.Nome)%>
                    </th>
                <%Next%>
            </tr>
            <% dim contador as integer = 0 %>
            <% For Each tamanho As Nucleo.TamanhoPapel In Model.ListaTamanho%>
                <tr>
                    <td style="text-align:center">
                        <%=Html.Encode(tamanho.Nome)%>
                    </td>
                    
                    <% For Each papel As Nucleo.TipoPapel In Model.ListaPapel%>
                        <td>
                            <div id='<%=html.encode(String.format("Configuracao{0}",contador))%>' >
                                <%Html.RenderAction("NomeDaPartialView", "NomeControladora", New With {.idTamanho = tamanho.Id, .idPapel = papel.Id, .celula = contador})%>
                            </div>
                            <%contador = contador + 1 %>
                        </td>
                    <%Next%>
                </tr>
            <%Next%>
                
        </table>

    A partial view é criada dentro de 2 For´s, pois eu crio uma tabela, sendo a partialView uma célula dessa tabela. O UpdateTargetId está referenciando a div que contém a chamada da partialView.

    Qualquer dúvida ou crítica só falar. Comecei a aprender MVC esse ano, então posso não estar sabendo utilizar as tecnologias de forma adequada.

    Obrigado pela atenção.

    Monday, April 12, 2010 12:11 PM
  • Desculpe minha ignorância Wilian, mas no meu caso, como ficaria o código postado por você?

            $("#id_do_botao_enviar").click(function() {
                $.ajax({
                    type: "POST",
                    url: "/Nome_do_Controller/Sua_Action",
                    success: function(data) {
                        $("#divResultado").html(data);
                        $("input:text").trigger("applymask");
                    },
                    error: function(XMLHttpRequest, textStatus) {
                        alert(textStatus);
                    }
                });
            });

    O "#id_do_botao_enviar" é dinâmico. Como pode visto no código que postei, a partialview é criada várias vezes, sendo que cada partialView possui 1 botao submit com id único.

     

    Monday, April 12, 2010 12:21 PM
  • Fala mkoka blz?

    Olha não tem problema o id do botão ser dinamico, voce pode utilizar o seletor jQuery apontando pra uma classe css, então desta maneira basta indicar a classe em seu botão dinamico.

    Exemplo: //seu seletor $('.classe_btn')

    Como ficaria a implementação :

           $(".classe_btn").click(function() {
                $.ajax({
                    type: "POST",
                    url: "/Nome_do_Controller/Sua_Action",
                    success: function(data) {
                        $("#divResultado").html(data);
                        $("input:text").trigger("applymask");
                    },
                    error: function(XMLHttpRequest, textStatus) {
                        alert(textStatus);
                    }
                });
            });

           //Seu botão, pode ser um tipo button já que voce irá utilizar ajax

          <inputtype='button'class='classe_btn' id='<%=String.Format("Botao{0}", ViewData("Celula"))%>'      value="salvar"style="display:none;"/>

    Olhei seu exemplo, e esta um pouco confuso mesmo, segue algumas dicas. 

    A parte de renderizar seu form não é necessário utilizar uma RenderAction, voce pode utilizar o RenderPartial, e seu form pode ser um ascx, dessa maneira não será necessário criar uma action especifica. Vi tambem que voce utilizou o "getElementById", blz mas já que voce esta utilizando e carregando o jQuery devido a máscara dos campos, pode utilizar o jQuery tambem para selecionar seus elementos, aos invés de usar "getElemenById('seu_id')", use "$('#seu_id')" que é mais simples de codificar. Posta os resultados depois.

    Eu recentemente li um livro dos cabeças do MVC, e eles disponibilizaram a primeira parte com mais de 100 páginas gratuitamente, ensinam a utilizar melhores práticas e reutilização de código, uso do membership, de uma olhadinha no endereço abaixo para donwload que vale muito apena.

    http://www.wrox.com/WileyCDA/Section/id-321793.html

     

    Thursday, April 15, 2010 10:12 PM
  • Olá Wilian, tudo bem?

    Eu vou tentar aplicar as alterações indicadas por você.

    Bom, só para explicar, eu utilizo um renderAction pelo seguinte motivo:

    Essa página recebe 2 listas, tamanho e tipo. Eu crio uma tabela de TamanhoXTipo. Para cada configuracação de tamanhoxtipo eu chame o renderaction passando os id´s do tamanho e do tipo, essa action pesquisa no banco a configuração e joga em uma partialview.

    Não consigo imaginar fazer isso com renderPartial. Eu teria que carregar todas as configurações salvar em algum lugar e criar as partialViews passando os objetos? Não ficaria pior?

    Bom, como eu disse anteriormente, eu tenho pouca experiência com desenvolvimento Web. Esse seria o início do meu aprendizado. Não utilizei o JQuery pq eu não tinha muito conhecimento.

    Obrigado pela atenção e observações.

    Friday, April 16, 2010 12:15 PM