Gutenberg Infinite Loop - wordpress

I'm working on building a Gutenberg block but it seems I keep getting an infinite loop. How can I invoke the rest API only once?
I am trying to get a list of officers - custom post type - but as the initial call doesn't provide the featured image I thought I should loop through and add the images "manually". If there is a better approach please do let me know.
registerBlockType('test/officers-block', {
title: __('Officers Block', 'test'),
description: __('Block to generate the officers block', 'test'),
icon: '',
category: 'test',
attributes: {
title: {
type: 'string',
},
posts: {
type: 'array',
}
},
edit: ({ attributes, setAttributes }) => {
const {
title,
posts,
} = attributes
// Request data
const data = useSelect((select) => {
return select('core').getEntityRecords('postType', 'officers', { per_page: -1 });
});
const isLoading = useSelect((select) => {
return select('core/data').isResolving('core', 'getEntityRecords', [
'postType', 'officers',
]);
});
const setOfficers = ( data ) => {
let officerData = [];
data.map(( officer ) => {
wp.apiFetch( { path: '/wp/v2/media/' + officer?.featured_media } ).then( function( image ){
officerDataEach.title = officer?.title?.rendered
officerDataEach.content = officer?.content?.rendered
officerDataEach.job = officer?.meta?._job_title
officerDataEach.phone = officer?.meta?._phone
officerDataEach.email = officer?.meta?._email
officerDataEach.image = image?.media_details?.sizes?.full?.source_url
officerData.push( officerDataEach )
})
})
console.log(officerData);
setAttributes( { posts: officerData } )
}
if( !isLoading && data ){
setOfficers( data );
}
if ( isLoading && !data ) {
return <h3>Loading...</h3>;
}
...
Thanks in advance

Related

Using Vue, but I can't query information from Firebase to display values in a chart/graph (google charts or GChart). "Error: Table has no columns."

This code is inside a .vue file. Receiving the "Error: Table has no columns." Inside the methods function, it won't receive the values from firebase to display a chart/graph to web app. What am I doing incorrectly? I think the values am I trying to receive inside "chartData:[ ]" or "mounted()" is incorrect and may be causing the issue. Any help is much appreciated.
export default {
name: "App",
components: {
GChart
},
methods: {
getHumidity(){
get(
query(ref(db, auth.currentUser.uid + "/Environment/humidity"),
orderByChild("humidity")
)
).then((snapshot) => {
if (snapshot.exists()) {
console.log(snapshot.val());
for (const item in snapshot.val()) {
this.pgoods.push({
humidity: snapshot.val()[item].humidity,
expir: snapshot.val()[item].humidity,
});
}
} else {
this.pgoods = [];
}
return float(snapshot.val());
});
}
getPressure(){
get(
query(ref(db, auth.currentUser.uid + "/Environment/pressure"),
orderByChild("pressure")
)
).then((snapshot) => {
if (snapshot.exists()) {
console.log(snapshot.val());
for (const item in snapshot.val()) {
this.pgoods.push({
pressure: snapshot.val()[item].pressure,
expir: snapshot.val()[item].pressure,
});
}
} else {
this.pgoods = [];
}
return float(snapshot.val());
});
}
getTime(){
get(
query(ref(db, auth.currentUser.uid + "/Environment/time"),
orderByChild("time")
)
).then((snapshot) => {
if (snapshot.exists()) {
console.log(snapshot.val());
for (const item in snapshot.val()) {
this.pgoods.push({
time: snapshot.val()[item].time,
expir: snapshot.val()[item].time,
});
}
} else {
this.pgoods = [];
}
return float(snapshot.val());
});
},
},
data(){
return{
chartData: [
["Time", "Pressure", "Humidity"],
[this.getTime(), this.getPressure(), this.getHumidity()],
[this.getTime(), this.getPressure(), this.getHumidity()],
],
},
mounted(){
this.getTemperature();
this.getHumidity();
},
}

Run a piece of code when block is loaded in wordpress

I have made a custom gutenberg block:
(function(blocks, components, element) {
var el = element.createElement;
var registerBlockType = blocks.registerBlockType;
var TextControl = components.TextControl;
registerBlockType("blocks/test-block", {
title: "Test Block",
description: "A custom block.",
icon: "businessman",
category: "common",
attributes: {
headline: {
type: "string"
}
},
edit: function(props) {
var headline = props.attributes.headline;
var onHeadlineChange = function(val) {
props.setAttributes({
headline: val
});
};
return el(TextControl, {
value: headline,
label: "Headline",
onChange: onHeadlineChange
});
},
save: function(props) {
alert('');
return el(
"h3",
{
className: "headline"
},
props.attributes.headline
);
}
});
})(window.wp.blocks, window.wp.components, window.wp.element);
I want to run a function when the block is loaded on front end.
I tried in save function but it only work when the block is saved on wp-dashboard.
Is there any way by which I can run a function when block is loaded?
You can use render callback parameter in register block type inside your PHP file.
like
register_block_type(
'blocks/test-block', array(
'editor_script' => 'index-js',
'render_callback' => 'recent_posts_block'
)
);
function recent_posts_block($attributes){
//your code here
}

performance remote el-select option 3000 items slow and crush?

Hello this is my first time. I have problem with like that I have 3000 items and I use framework like vue, element-ui and meteor. I pull all the items through a remote el-select that selects to add more remote select array object.I don't know why it slow performance and crush.
This is my picture
// Find item opts method
_getItemOpts(query, type) {
type = type || 'remote'
let exp = new RegExp(query)
let selector = {}
if (exp) {
selector = {
itemType: { $ne: 'Bundle' },
// , 'Sale'
activityType: { $in: ['Purchase'] },
status: 'Active',
$or: [
{ name: { $regex: exp, $options: 'i' } },
{ refNo: { $regex: exp, $options: 'i' } },
{ barcode: { $regex: exp, $options: 'i' } },
],
}
}
// Find item
findItems
.callPromise({ selector: selector })
.then(result => {
// console.log(result)
if (type == 'remote') {
this.itemOpts = result
}
this.loading = false
})
.catch(err => {
this.loading = false
Notify.error({ message: err })
})
},
Please help me.
Well no magick is here. U tryin to add to DOM 3000 of elements, so no wonder its crashes. Try to narrow results, for example show them only when user enters 3 letters

Why doesn't ui-grid in Angular Meteor show its data when filter is activated?

Hello I have a problem
Working:
Meteor
Angular Meteor
ui-grid
I follow the plunker example in documentation ui-grid link
The problem is that the data don't show when filters are activated.
I have no errors in console.
I put my code:
html file
<button id='toggleFiltering' ng-click="inventario.toggleFiltering()" class="btn btn-success">Toggle Filtering</button>
<div id="grid1" ui-grid="inventario.gridOptions" class="grid"></div>
js file
class Inventario {
constructor($scope, $reactive, $uibModal, $http, uiGridConstants) {
'ngInject';
$reactive(this).attach($scope);
this.$uibModal = $uibModal;
var today = new Date();
var nextWeek = new Date();
this.highlightFilteredHeader = (row, rowRenderIndex, col, colRenderIndex) => {
if( col.filters[0].term ){
return 'header-filtered';
} else {
return '';
}
};
this.gridOptions = {
enableFiltering: true,
onRegisterApi: (gridApi) => {
this.gridApi = gridApi;
},
columnDefs: [
// default
{ field: 'name', headerCellClass: this.highlightFilteredHeader },
// pre-populated search field
{ field: 'gender', filter: {
term: '1',
type: uiGridConstants.filter.SELECT,
selectOptions: [ { value: '1', label: 'male' }, { value: '2', label: 'female' }, { value: '3', label: 'unknown'}, { value: '4', label: 'not stated' }, { value: '5', label: 'a really long value that extends things' } ]
},
cellFilter: 'mapGender', headerCellClass: this.highlightFilteredHeader },
// no filter input
{ field: 'company', enableFiltering: false, filter: {
noTerm: true,
condition: (searchTerm, cellValue) => {
return cellValue.match(/a/);
}
}},
// specifies one of the built-in conditions
// and a placeholder for the input
{
field: 'email',
filter: {
condition: uiGridConstants.filter.ENDS_WITH,
placeholder: 'ends with'
}, headerCellClass: this.highlightFilteredHeader
},
// custom condition function
{
field: 'phone',
filter: {
condition: (searchTerm, cellValue) => {
var strippedValue = (cellValue + '').replace(/[^\d]/g, '');
return strippedValue.indexOf(searchTerm) >= 0;
}
}, headerCellClass: this.highlightFilteredHeader
},
// multiple filters
{ field: 'age', filters: [
{
condition: uiGridConstants.filter.GREATER_THAN,
placeholder: 'greater than'
},
{
condition: uiGridConstants.filter.LESS_THAN,
placeholder: 'less than'
}
], headerCellClass: this.highlightFilteredHeader},
// date filter
{ field: 'mixedDate', cellFilter: 'date', width: '15%', filter: {
condition: uiGridConstants.filter.LESS_THAN,
placeholder: 'less than',
term: nextWeek
}, headerCellClass: this.highlightFilteredHeader
},
{ field: 'mixedDate', displayName: "Long Date", cellFilter: 'date:"longDate"', filterCellFiltered:true, width: '15%',
}
]
};
$http.get('https://cdn.rawgit.com/angular-ui/ui-grid.info/gh-pages/data/500_complex.json')
.success((data) => {
this.gridOptions.data = data;
this.gridOptions.data[0].age = -5;
data.forEach( function addDates( row, index ){
row.mixedDate = new Date();
row.mixedDate.setDate(today.getDate() + ( index % 14 ) );
row.gender = row.gender==='male' ? '1' : '2';
});
});
this.toggleFiltering = () => {
this.gridOptions.enableFiltering = !this.gridOptions.enableFiltering;
this.gridApi.core.notifyDataChange( uiGridConstants.dataChange.COLUMN );
};
}
}
const name = 'inventario';
// Módulo
export default angular
.module(name, [
uiRouter,
EditarArticulo
])
.component(name, {
templateUrl: `imports/ui/components/${name}/${name}.html`,
controllerAs: name,
controller: Inventario
})
.config(config)
.filter('mapGender', function() {
var genderHash = {
1: 'male',
2: 'female'
};
return function(input) {
if (!input){
return '';
} else {
return genderHash[input];
}
};
});
Given that everything seems to work when filtering is disabled, you must have a problem with the (multiple) filters you have declared.
It is most likely a combination of the filters that is excluding all of your data. Start by commenting out all of the filters (you should see all the data), and then re-introduce the filters one by one until you see the problem again.
This will narrow down the problem, and allow you to see which filter is wrong.

How to join firebase data with the newest angularfire and fire util?

I have a list of categories and a list of products:
{
categories: {
'myCategoryId': {
name: 'my category name',
products: {
'first': true,
'second': true
}
}
},
products: {
'first': {
name: 'my product name',
categoryId: 'myCategoryId'
},
'second': {
name: 'my second product name',
categoryId: 'myCategoryId'
}
}
}
In my sidebar I want to show a joined list of categories with product names so I need some joined structure like:
{
categoriesWithNames: {
'myCategoryId': {
name: 'my category name',
products: {
'first': {
name: 'my product name'
},
'second': {
name: 'my second product name'
},
}
}
}
I know I can do this with Firebase util and AngularFire, but I've tried few different methods and I cannot grasp the concept of joining denormalized data in Firebase. Can anyone help me?
Code
var myApp = angular.module("myApp", ["firebase"]);
var FBURL = "MYFBURL";
var FBEVENTS = {
'deleted':'child_removed',
'added':'child_added'
};
myApp.controller('MyController', ['$scope', '$firebase',
function ($scope, $firebase){
var base = fb(FBURL);
function fb(url) {
return new Firebase(url);
}
function fbChild(attrs) {
return $firebase(typeof attrs === "string" ? base.child(attrs) : base.child(attrs.join("/")));
}
function $a(fbChild) {
return fbChild.$asArray();
}
function $o(fbChild) {
return fbChild.$asObject();
}
var products = fbChild('products');
var categories = fbChild('categories');
$scope.products = $a(products);
$scope.categories = $a(categories);
$scope.products.$loaded().then(function(){
$scope.categories.$watch(function (snapshot) {
console.log('snapshot is', snapshot);
if(snapshot.event!==FBEVENTS.deleted) {
var foundCat = $scope.categories.$getRecord(snapshot.key);
foundCat.products = _.map(foundCat.products, function (val, key){
if (val !== true)
return val;
return $scope.products.$getRecord(key);
});
}
});
});
}

Resources