【问题标题】:Using gravity forms with an asynchronous site在异步站点中使用重力形式
【发布时间】:2018-01-10 23:09:33
【问题描述】:

我有一个 wordpress 网站,它使用 angular 来处理 ajaxed 页面加载。直接加载页面时,重力形式按预期加载。如果您从非重力表单页面加载,然后导航到带有表单的页面,您将一无所获。

这可能与嵌入表单下方的脚本 grav 表单有关。所以我想知道是否有办法在通过ajax加载后初始化表单。

我可以在functions.php中使用这个页面加载后,使用一些html、jquery魔术来通过ajax获取表单:

gravity_form_enqueue_scripts( $form_id, true );
echo gravity_form($form_id, false, false, false, null, true, 12, true);

当我将结果注入 DOM 时,我只是得到这个控制台错误:

gformInitSpinner is not defined

即使我以新的 html 为目标并显示以 html 形式出现的表单,我也会得到一个无法正常工作的严重格式错误的表单。显然是因为脚本没有得到评估,并且 js 错误无论如何都会阻止它。

那么有谁知道是否有办法让重力表单在异步站点上工作?或者您是否可以使用 ajax 加载功能表单?

我无法使用gravity_form_enqueue_scripts 填充入队系统,因为任何时候都可能生成任意数量的表单。这不是一个实际的解决方案。

【问题讨论】:

    标签: angularjs ajax wordpress gravity-forms-plugin


    【解决方案1】:

    好吧,不感谢重力表格开发团队和整个互联网,我们为我们所有人提供了一个解决方案,他们的任务似乎是一个非常常用的插件的明显使用......

    首先,设置您的functions.php文件,以便它可以处理这个:

    // filter the Gravity Forms button type
    add_filter( 'gform_submit_button', 'form_submit_button', 10, 2 );
    function form_submit_button( $button, $form ) {
        return "<button class='btn btn-green' type='submit' id='gform_submit_button_{$form['id']}'>Submit</button>";
    }
    
    // Hook up the AJAX actions
    add_action( 'wp_ajax_nopriv_gf_button_get_form', 'gform_ajax_get_form' );
    add_action( 'wp_ajax_gf_button_get_form', 'gform_ajax_get_form' );
    
    // Add the "button" action to the gravityforms shortcode
    // e.g. [gravityforms action="button" id=1 text="button text"]
    add_filter( 'gform_shortcode_form', 'gform_shortcode', 10, 3 );
    
    function gform_shortcode( $shortcode_string, $attributes, $content )
    {
        $a = shortcode_atts( array(
            'id' => 0,
            'text' => 'Show me the form!',
        ), $attributes );
    
        $form_id = absint( $a['id'] );
    
        if ( $form_id < 1 ) {
            return 'Missing the ID attribute.';
        }
    
        $ajax_url = admin_url( 'admin-ajax.php' );
    
        $html = sprintf('<div ng-controller="GavityFormController as garvityFormCtrl" ng-init="init(\'%s\', \'%s\')"><div class="gform_container" ng-include="form"></div></div>', $form_id, $ajax_url);
    
        return $html;
    }
    
    function gform_ajax_get_form(){
        $form_id = isset( $_GET['form_id'] ) ? absint( $_GET['form_id'] ) : 0;
        $form = gravity_form($form_id, false, false, false, false, true, 0, false);
    
        $form = str_replace('text/javascript', 'text/ng-javascript', $form);
        $form = str_replace('<script ', '<script lazy-js ', $form);
    
        echo $form;
    
        die();
    }
    
    add_filter("wp_footer", "init_gf_scripts");
    function init_gf_scripts() {
        global $wpdb;
    
        //obviously change this if your prefix is different
        $sql = "SELECT `id` FROM `wp_rg_form` WHERE `is_active` = 1 AND `is_trash` = 0";
        $res = $wpdb->get_results($sql);
        foreach($res AS $r)
        {
            gravity_form_enqueue_scripts( $r->id, true );
        }
    }
    

    下一步可能因您设置主 js 文件的方式而异。必要的要点如下。通常还有很多,但希望你能明白。

    (function(){
        require('./directives/forms/form');
    
        var util = require('./util');
    
        var app = angular.module('yourapp', [
            'yourapp-form',
        ])...
    

    util.js ...可能是一个普通文件。我不确定它是否真的与实际问题有关,但它是表单组件所必需的,所以你去吧:

    module.exports = (function() {
        var api = {
            isMobileOrSmaller: function () {
                return $(window).width() < 681
            },
            findByProp: function (data, value, prop) {
                prop = prop || 'id';
                return $.grep(data, function(e){ return e[prop] == value; });
            },
            getIndexOf: function (collection, value, prop) {
                prop = prop || 'id';
                return collection.map(function (e) { return e[prop] }).indexOf(value);
            },
            roundTo: function (value, to) {
                to = to || 10;
                return Math.floor(value/to) * to;
            },
            debounce: function(func, wait, immediate) {
                var timeout;
                return function() {
                    var context = this, args = arguments;
                    var later = function() {
                        timeout = null;
                        if (!immediate) func.apply(context, args);
                    };
                    var callNow = immediate && !timeout;
                    clearTimeout(timeout);
                    timeout = setTimeout(later, wait);
                    if (callNow) func.apply(context, args);
                };
            },
            getScrollbarWidth: function () {
                return $(window).width();// - $('#siteBody > div').width();
            },
            getRandomInt: function (min, max) {
                return Math.floor(Math.random() * (max - min + 1)) + min;
            }
        };
    
        return api;
    })();
    

    还有表单指令...

    /directives/forms/form.js

    module.exports = (function() {
        var api = {};
    
        var form = angular.module('yourapp-form', [
        ]).directive('lazyJs', [function () {
            return {
                restricted: 'A',
                link: function (scope, element) {
                    var code = element.text();
                    var tmpFunc = new Function(code);
    
                    scope.$on('GavityFormController::includeContentLoaded', function () {
                        tmpFunc();
    
                        if(window['gformInitDatepicker']) {
                            gformInitDatepicker();
                        }
    
                        if (window['gformInitPriceFields']) {
                            gformInitPriceFields();
                        }
                    })
                }
            }
        }]).controller('GavityFormController', ['$scope', '$rootScope', '$element', '$http', function ($scope, $rootScope, $element, $http) {
            var panel = this,
                formId = 0; 
    
            $scope.form = '';
            $scope.init = function (id, url) {
                formId = id;
                $scope.form = url + '?action=gf_button_get_form&form_id=' + id
            }
    
            $scope.$on('$includeContentLoaded', function(e, src){
                if ($('#gform_wrapper_' + formId).length > 0) {
                    $scope.$broadcast('GavityFormController::includeContentLoaded');
                }
            });
        }]);
    
        //registerring componenets
        var radio = require ('./radio');
        radio.register(form);
    
        var select = require ('./select');
        select.register(form);
    
        var text = require ('./text');
        text.register(form);
    
        var check = require ('./check');
        check.register(form);
    
        var textarea = require('./textarea');
        textarea.register(form);
    
        api.form = form;
    
    
        return api;
    })();
    

    这些都是必需的表单组件文件:

    radio.js:

    module.exports = (function() {
        var api = {};
    
        api.register = function (form) {
            form.directive('myappRadio', function(){
                return {
                    restricted: 'E',
                    transclude: true,
                    replace: true,
                    scope: {
                        model: '=model'
                    },
                    template: function ($element, $attrs) {
                        return '<div class="ipt ipt-radio"> \
                                    <div  ng-transclude></div> \
                                    <label for="' + $attrs.for + '">' + $attrs.label + '</label> \
                                </div>';
    
                    }
                }
            });
        }
    
    
        return api;
    })();
    

    select.js:

    var util = require('./../../util');
    
    module.exports = (function() {
        var api = {};
    
        api.register = function (form) {
            form.directive('select', ['$timeout', function($timeout){
                return {
                    restricted: 'E',
                    link: function($scope, $element, $attrs) {
                        $timeout(function () {
                            Selectize.define('input_modify', function(options) {
                                var self = this;
    
                                this.setup = (function() {
                                    var original = self.setup;
                                    return function() {
                                        original.apply(this, arguments);
    
                                        this.$control.find('input').attr('id', '');
                                    };
                                })();
                            });
    
                            $($element).selectize({
                                plugins: ['remove_button', 'input_modify']
                            });
                        }, 10);
                    }
                }
            }])
        }
    
    
        return api;
    })();
    

    text.js

    module.exports = (function() {
        var api = {};
    
        api.register = function (form) {
    
            form.directive('myapptext', function(){
                return {
                    restricted: 'E',
                    scope: {
                        model: '=model',
                        ngrequired: '='
                    },
                    link: function(scope, element, attrs, controllers) {
                        var panel = this;
    
                        scope.isActive = scope.model !== '';
                        scope.required = false;
    
                        if (attrs.required === "")
                            scope.required = true;
    
                        if (typeof scope.ngrequired !== "undefined")
                            scope.required = scope.ngrequired;
    
                        scope.onEnter = function () {
                            scope.isActive = true;
                        }
    
                        scope.onLeave = function () {
                            if (scope.model == '' || typeof scope.model == 'undefined'){
                                scope.isActive = false;
                            }
                        }
    
                        scope.$watch('ngrequired', function(value){
                            scope.required = scope.ngrequired;
                        });
                    },
                    template: function (element, attr) {
                        var id = attr.id || 'frm-' + attr.name,
                            type = attr.type || 'text';
                            value = attr.value || '';
                        return '<div class="ipt-text-wrappper" ng-class="{\'m-active\': isActive}"> \
                                    <input ng-required="required" ng-focus="onEnter()" ng-blur="onLeave()" ng-model="model" id="' + id + '" type="' + type + '" name="' + attr.name + '" value="' + value + '" class="ipt ipt-text"> \
                                    <label ng-click="onEnter()" for="' + id + '">' + attr.label + '</label> \
                                </div>';
                    }
                }
            });
        }
    
    
        return api;
    })();
    

    check.js:

    module.exports = (function() {
        var api = {};
    
        api.register = function (form) {
            form.directive('myappCheck', function(){
                return {
                    restricted: 'E',
                    transclude: true,
                    replace: true,
                    scope: {
                        model: '=model'
                    },
                    template: function ($element, $attrs) {
                        return '<div class="ipt ipt-radio"> \
                                    <div  ng-transclude></div> \
                                    <label for="' + $attrs.for + '">' + $attrs.label + '</label> \
                                </div>';
    
                    }
                }
            });
        }
    
    
        return api;
    })();
    

    textarea.js:

    module.exports = (function() {
        var api = {};
    
        api.register = function (form) {
            form.directive('myapptextarea', function(){
                return {
                    restricted: 'E',
                    scope: {
                        model: '=model',
                        ngrequired: '='
                    },
                    link: function(scope, element, attrs, controllers) {
                        var panel = this;
    
                        scope.isActive = scope.model !== '';
                        scope.required = false;
    
                        if (attrs.required === "")
                            scope.required = true;
    
                        if (typeof scope.ngrequired !== "undefined")
                            scope.required = scope.ngrequired;
    
                        scope.onEnter = function () {
                            scope.isActive = true;
                        }
    
                        scope.onLeave = function () {
                            if (scope.model == '' || typeof scope.model == 'undefined'){
                                scope.isActive = false;
                            }
                        }
    
                        scope.$watch('ngrequired', function(value){
                            scope.required = scope.ngrequired;
                        });
                    },
                    template: function (element, attr) {
                        var id = attr.id || 'frm-' + attr.name,
                            value = attr.value || '';
                        return '<div class="ipt-text-wrappper" ng-class="{\'m-active\': isActive}"> \
                                    <textarea ng-required="required" ng-focus="onEnter()" ng-blur="onLeave()" ng-model="model" id="' + id + '" name="' + attr.name + '" class="ipt ipt-textarea">' + value + '</textarea> \
                                    <label ng-click="onEnter()" for="' + id + '">' + attr.label + '</label> \
                                </div>';
                    }
                }
            });
        }
    
    
        return api;
    })();
    

    就是这样。我个人通过调用gravity_form函数在php中调用它:

    <?php echo gravity_form(1, false, false, false, '', true, 12); ?>
    

    但我认为 WYSIWYG 中的基本嵌入表单也可以工作。

    这不是我自己写的,所以我不确定我是否可以回答问题,但如果你有问题,请随时提问

    【讨论】:

    • 解释你的反对意见!这行得通,我没有得到 GRAV 形式的支持!什么,你不喜欢人们在支付失败的情况下喊出受欢迎的产品吗?好吧,继续!说明为什么您认为必须将重力表格放在客户网站上的其他人不应该有其他任何地方都没有记录的解决方案......我很想听听
    • 我看不出你在哪里指定出了什么问题。相反,我看到一堆代码转储,没有解释它们如何解决给定问题、为什么需要它们或它们做什么。没用处。这更像是一个教程而不是一个答案,但没有解释。
    • 你不明白“那么有没有人知道是否有办法让重力表单与异步站点一起工作?或者你是否可以使用 ajax 加载功能表单?” - 呃......我用我用来使它与异步站点一起工作的代码回答了我自己的问题,如页面上的所有内容所示。相信我,我完全被重力形式缺乏反应激怒了,我并不孤单。地球上任何需要使用有角度的重力形式的人都不会很难将它们拼凑在一起
    • 如果他们觉得有用,他们可以投票。 :)
    • 说真的,没用?!在我没有得到任何人的回应后,我有该死的体面回来回答这个问题。一位同事碰巧曾经不得不解决这个问题。我本可以把它留在黑暗中,与任何人分享。 F,伙计。否决回答“你尝试谷歌搜索”的白痴 - 如果你尝试了上面的代码并且它直接不起作用那么肯定,整天都投反对票。否则就继续前进
    猜你喜欢
    • 1970-01-01
    • 2014-07-31
    • 2014-11-13
    • 1970-01-01
    • 2015-08-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多