在异步站点中使用重力形式
Using gravity forms with an asynchronous site
我有一个使用 angular 处理 ajaxed 页面加载的 wordpress 网站。直接加载页面时,重力会按预期形成加载。如果您从非重力表单页面加载然后导航到带有表单的页面,您将一无所获。
这可能与表单下方嵌入的脚本 grav 表单有关。所以我想知道是否有办法在通过 ajax.
加载后初始化表单
我可以使用一些 html、jquery 魔法在页面加载后通过 ajax 获取表单 functions.php:
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 填充入队系统,因为随时可能生成任意数量的表格。这不是一个实际的解决方案。
好吧,不感谢重力形式开发团队和整个互联网,我们为我们所有人提供了一个解决方案,我们的任务似乎是一个非常常用的插件的明显使用...
首先,设置您的 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 中的基本嵌入式表格也可以使用。
这不是我自己写的,所以我不确定我是否可以回答问题,但如果你有问题,请随时提问
我有一个使用 angular 处理 ajaxed 页面加载的 wordpress 网站。直接加载页面时,重力会按预期形成加载。如果您从非重力表单页面加载然后导航到带有表单的页面,您将一无所获。
这可能与表单下方嵌入的脚本 grav 表单有关。所以我想知道是否有办法在通过 ajax.
加载后初始化表单我可以使用一些 html、jquery 魔法在页面加载后通过 ajax 获取表单 functions.php:
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 填充入队系统,因为随时可能生成任意数量的表格。这不是一个实际的解决方案。
好吧,不感谢重力形式开发团队和整个互联网,我们为我们所有人提供了一个解决方案,我们的任务似乎是一个非常常用的插件的明显使用...
首先,设置您的 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 中的基本嵌入式表格也可以使用。
这不是我自己写的,所以我不确定我是否可以回答问题,但如果你有问题,请随时提问