2017-04-17 59 views
0

在我的symfony 3项目中,我制作了一个表单,我想通过使用knockout.js通过ajax提交。但对于某些人来说,它使浏览器重定向到动作而不是通过ajax进行。Symfony Knockout:自定义绑定处理程序无法侦听绑定处理程序

,我想用Ajax提交一个名为app/FosUserBundle/views/Registration/register.html.twig文件的形式是:

{% extends "FOSUserBundle::layout.html.twig" %} 

{% block fos_user_content %} 

    {% form_theme form '::themes/register-form-theme.html.twig' %} 
    {% trans_default_domain 'FOSUserBundle' %} 

<div class="container" data-bind="with:registerVm"> 
    <div class="register-box"> 
    <div class="register-logo"> 
     <h1>PhotoShare!</h1> 
    </div> 
    <div class="register-box-body"> 
     <p class="login-box-msg">Register a new membership</p> 
     {{ form_start(form, {'method': 'post', 'action': path('fos_user_registration_register'),'attr':{'data-bind':'formSubmitAjax:\{\'success\':registerComplete\}'}}) }} 
     {{ form_widget(form) }} 
     <div class="row"> 
      <div class="col-xs-4"> 
      <input type="submit" class="btn btn-primary btn-block btn-flat" value="{{ 'registration.submit'|trans }}" /> 
      </div> 
     </div> 
     {{ form_end(form) }} 
    </div> 
</div> 

{% endblock fos_user_content %} 

的形式需要使用以下knockout.js自定义绑定处理程序:

define(['knockout','jquery'],function(ko,$) 
{ 

    ko.bindingHandlers.formSubmitAjax={ 
    init: function(element, valueAccessor, allBindingsAccessor) 
    { 
     var callbacks=valueAccessor(); 

     var action=$(element).attr('action'); 
     var method=$(element).attr('method'); 
     var dataType=(callbacks && callbacks['type'])?callbacks['type']:'json';//By default use Json 


     $(element).submit(function(e) 
     { 
     e.preventDefault(); 
     var form_data= $(this).serialize(); 

     $.ajax({ 
      'method':method, 
      'data':form_data, 
      'url':action, 
      'beforeSend':function() 
      { 
      if(typeof callbacks['beforeSend'] === 'function') callbacks['beforeSend'](); 
      }, 
      'success':function(data,textStatus,jqXHR) 
      { 
      if(typeof callbacks['success'] === 'function') callbacks['success'](data,textStatus,jqXHR); 
      }, 
      'error':function(jqXHR,textStatus,errorThrown) 
      { 
      if(typeof callbacks['error'] === 'function') callbacks['error'](jqXHR,textStatus,errorThrown); 
      }, 
      'complete':function(jqXHR,textStatus) 
      { 
      if(typeof callbacks['always'] === 'function') callbacks['always'](jqXHR,textStatus); 
      } 
     }); 
     }); 
    } 
    }; 

}) 

这种形式通过pager.js呈现在这个树枝模板上:

{% extends "base.html.twig" %} 

{% set classes=''%} 

{% block javascriptsHeader %} 
    <script src="{{asset('assets/vendor/require.js')}}" data-main="{{path('main_javascript')}}" ></script> 
{% endblock %} 

{% block stylesheets %} 
    {{ parent() }} 
    <link rel="stylesheet" type="text.css" href="{{ asset('assets/vendor/xeditable/css/bootstrap-editable.css') }}" > 
    <style> 
    #message-area{ 
     z-index:9999; 
    } 
    .page{ 
     min-height:100%; 
     min-width:100%; 
    } 
    </style> 
{% endblock %} 

{% block body %} 
    <div id="message-area"></div> 
    <div class="hold-transition register-page page" data-bind="page: {id:'register', title:'Register', role:'start', sourceOnShow: '{{ path('fos_user_registration_register') }}', withOnShow:function(a){registerVm.init();},with:registerVm}"></div> 
{% endblock %} 

那ex倾向于以下基本模板:

<!DOCTYPE html> 
<html> 
    <head> 
     <meta charset="UTF-8" /> 
     <title>{% block title %}Welcome!{% endblock %}</title> 
     <meta http-equiv="X-UA-Compatible" content="IE=edge"> 
     <meta name="viewport" content="width=device-width, initial-scale=1"> 

     {% block stylesheets %} 
      <link rel="stylesheet" type="text/css" href="{{asset('assets/vendor/bootstrap/css/bootstrap.css')}}" > 
      <link rel="stylesheet" type="text/css" href="{{asset('assets/vendor/adminlte/adminlte.css')}}" > 
      <link rel="stylesheet" type="text/css" href="{{asset('assets/vendor/adminlte/skin-blue.css')}}" > 
     {% endblock %} 
     <link rel="icon" type="image/x-icon" href="{{ asset('favicon.ico') }}" /> 

     {% block javascriptsHeader %} 
     {% endblock %} 

    </head> 
    <body class="{{ classes }}"> 
     {% block body %} 
     {% endblock body %} 

     {% block javascriptsFooter %} 

     {% endblock javascriptsFooter %} 
    </body> 
</html> 

所有需要的JavaScript我通过以下require.js模板,使其:

requirejs.config({ 
    baseUrl:'{{asset('assets')}}', 
    paths:{ 
    'text':'{{ asset('assets/vendor/text') }}', 

    'knockout':'{{ asset('assets/vendor/knockout') }}', 
    'pager':"{{asset('assets/vendor/pager')}}", 
    'bootstrap':"{{asset('assets/vendor/bootstrap/js/bootstrap')}}", 

    'jquery':"{{asset('assets/vendor/jquery')}}", 
    'jquery_ui':"{{ asset('assets/vendor/jquery-ui') }}", 

    'xeditable_bootstrap':"{{ asset('assets/vendor/xeditable/xeditable') }}", 
    'ko_xeditable':"{{ asset('assets/vendor/knockout/knockout.x-editable') }}", 

    'jquery-fileupload':"{{ asset('assets/vendor/jquery_fileupload/jquery.fileupload') }}", 
    'jquery-iframe':"{{ asset('assets/vendor/jquery_fileupload/jquery.iframe-transport') }}", 
    'jquery-ui-widget':"{{ asset('assets/vendor/jquery_fileupload/jquery.ui.widget') }}", 

    'masterViewModel':"{{ asset('assets/js/viewModels/masterViewModel') }}", 
    'registerViewModel':"{{ asset('assets/js/viewModels/registerPageViewModel') }}", 
    {% block Viewmodels %} 
    {% endblock %} 

    'formPost':"{{ asset('assets/js/bindingHandlers/formPost') }}", 

    'compMessage':"{{ asset('assets/js/components/message/message') }}", 
    'extBooleanToggle':'assets/js/extenders/booleanToggle', 
    }, 
    shim:{ 
    'pager': ['jquery', 'knockout'], 
    'jquery_ui':['jquery'], 
    'bootstrap':['jquery'], 
    'xeditable_bootstrap':['jquery-ui','bootstrap'], 
    'ko_xeditable':['xeditable_bootstrap'], 
    'jquery-fileupload':['jquery-iframe','jquery-ui-widget'], 
    'jquery-ui-widget':['jquery_ui'],//Jquery_ui already load jquery 
    'jquery-iframe':['jquery'] 
    {% block CustomShim %} 
    {% endblock %} 
    }, 
    waitSeconds: 200, 
}); 

define(['jquery','knockout','pager','masterViewModel','bootstrap'],function($,ko,pager,masterViewModel) 
{ 
    $(document).ready(function(){ 
     pager.extendWithPage(masterViewModel); 
     ko.applyBindings(masterViewModel); 
     pager.start(); 
    }); 
}); 

而母版视图模式,淘汰赛以及pager.js初始化IS拥有以下内容:

define(['knockout','jquery','registerViewModel'],function(ko,$,registervm){ 

    function MasterViewModel() 
    { 
     var self=this;  
     self.registerVm=new registervm(self); 
    } 

    return new MasterViewModel(); 
}) 

你的同伴有什么想法,为什么formSubmitAjax不会被调用?

+0

你可能会过早地应用绑定,我测试了你的'formSubmitAjax',它[工作正常](https://jsfiddle.net/ddv4vubd/)。所以尝试'$(document).ready'中的'setTimeout'来查看是否有问题 – Jag

+0

我已经设置了超时时间,但仍然存在问题。 –

回答

0

我把上require.js以下shim部分和工作就像一个魅力:

'masterViewModel':['registerViewModel'], 
'registerViewModel':['formPost'] 

所得的followimg main.js.twig

requirejs.config({ 
    baseUrl:'{{asset('assets')}}', 
    paths:{ 
    'text':'{{ asset('assets/vendor/text') }}', 

    'knockout':'{{ asset('assets/vendor/knockout') }}', 
    'pager':"{{asset('assets/vendor/pager')}}", 
    'bootstrap':"{{asset('assets/vendor/bootstrap/js/bootstrap')}}", 

    'jquery':"{{asset('assets/vendor/jquery')}}", 
    'jquery_ui':"{{ asset('assets/vendor/jquery-ui') }}", 

    'xeditable_bootstrap':"{{ asset('assets/vendor/xeditable/xeditable') }}", 
    'ko_xeditable':"{{ asset('assets/vendor/knockout/knockout.x-editable') }}", 

    'jquery-fileupload':"{{ asset('assets/vendor/jquery_fileupload/jquery.fileupload') }}", 
    'jquery-iframe':"{{ asset('assets/vendor/jquery_fileupload/jquery.iframe-transport') }}", 
    'jquery-ui-widget':"{{ asset('assets/vendor/jquery_fileupload/jquery.ui.widget') }}", 

    'masterViewModel':"{{ asset('assets/js/viewModels/masterViewModel') }}", 
    'registerViewModel':"{{ asset('assets/js/viewModels/registerPageViewModel') }}", 
    {% block Viewmodels %} 
    {% endblock %} 

    'formPost':"{{ asset('assets/js/bindingHandlers/formPost') }}", 
    //'debug':"{{ asset('assets/js/bindingHandlers/debug') }}", 

    'compMessage':"{{ asset('assets/js/components/message/message') }}", 
    'extBooleanToggle':'assets/js/extenders/booleanToggle', 
    }, 
    shim:{ 
    'pager': ['jquery', 'knockout'], 
    'jquery_ui':['jquery'], 
    'bootstrap':['jquery'], 
    'xeditable_bootstrap':['jquery-ui','bootstrap'], 
    'ko_xeditable':['xeditable_bootstrap'], 
    'jquery-fileupload':['jquery-iframe','jquery-ui-widget'], 
    'jquery-ui-widget':['jquery_ui'],//Jquery_ui already load jquery 
    'jquery-iframe':['jquery'], 
    'masterViewModel':['registerViewModel'], 
    'registerViewModel':['formPost'] 
    {% block CustomShim %} 
    {% endblock %} 
    }, 
    waitSeconds: 200, 
}); 

define(['jquery','knockout','pager','masterViewModel','bootstrap'],function($,ko,pager,masterViewModel) 
{ 
    $(document).ready(function(){ 
      pager.extendWithPage(masterViewModel); 
      ko.applyBindings(masterViewModel); 
      pager.start(); 
    }); 
}); 

并像魅力一样工作!

0

您需要确保在调用ko.applyBindings之前加载了绑定处理程序。事情是这样的:

define(['jquery','knockout','pager','masterViewModel','bootstrap', 'formPost'], function($,ko,pager,masterViewModel) 
{ 
    $(document).ready(function(){ 
     pager.extendWithPage(masterViewModel); 
     ko.applyBindings(masterViewModel); 
     pager.start(); 
    }); 
}); 
+0

不用再刷新。 –

相关问题