How to convert string to number within custom element?

I’m creating a custom element based on the built-in Bricks Counter element. The only change I need to make is to use a custom field entry in the Count To box. I’ve created a custom element and registered it successfully, but as far as I can see, the only way to get dynamic data into an element is to use a text field.

So, I replaced the number field with a text field, and I can now add dynamic data. But the data is text, and I need to convert it to a number to work with the bricksCounter script.

Where would I make that conversion? Is it possible?

<?php
namespace Bricks;

if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly

class Element_Dynamic_Counter extends Element {
	public $category = 'custom';
	public $name     = 'dynamic-counter';
	public $icon     = 'ti-dashboard';
	public $scripts  = [ 'bricksCounter' ];

	public function get_label() {
		return esc_html__( 'Dynamic Counter', 'bricks' );
	}

	public function enqueue_scripts() {
		wp_enqueue_script( 'bricks-counter' );
	}

	public function set_controls() {
		$this->controls['countFrom'] = [
			'tab'         => 'content',
			'label'       => esc_html__( 'Count from', 'bricks' ),
			'type'        => 'number',
			'small'       => false,
			'placeholder' => 0,
			'rerender'    => true,
		];

		$this->controls['countTo'] = [
			'tab'      => 'content',
			'label'    => esc_html__( 'Count to', 'bricks' ),
			'type'     => 'text',
			'small'    => false,
			'default'  => esc_html__( '1000', 'bricks' ),
			'rerender' => true,
		];

		$this->controls['duration'] = [
			'tab'         => 'content',
			'label'       => esc_html__( 'Animation in ms', 'bricks' ),
			'type'        => 'number',
			'small'       => false,
			'placeholder' => 1000,
			'rerender'    => true,
		];

		$this->controls['prefix'] = [
			'tab'            => 'content',
			'label'          => esc_html__( 'Prefix', 'bricks' ),
			'type'           => 'text',
			'inline'         => true,
			'hasDynamicData' => false,
			'rerender'       => true,
		];

		$this->controls['suffix'] = [
			'tab'            => 'content',
			'label'          => esc_html__( 'Suffix', 'bricks' ),
			'type'           => 'text',
			'inline'         => true,
			'hasDynamicData' => false,
			'rerender'       => true,
		];

		// Auto-set via JS: toLocaleString()
		$this->controls['thousandSeparator'] = [
			'tab'      => 'content',
			'label'    => esc_html__( 'Thousand separator', 'bricks' ),
			'type'     => 'checkbox',
			'rerender' => true,
		];
	}

	public function render() {
		$settings   = $this->settings;
		$count_from = isset( $settings['countFrom'] ) ? intval( $settings['countFrom'] ) : 0;
		$prefix     = ! empty( $settings['prefix'] ) ? $settings['prefix'] : false;
		$suffix     = ! empty( $settings['suffix'] ) ? $settings['suffix'] : false;

		$this->set_attribute(
			'_root',
			'data-bricks-counter-options',
			wp_json_encode(
				[
					'countFrom' => $count_from,
					'countTo'   => isset( $settings['countTo'] ) ? intval( $settings['countTo'] ) : 100,
					'duration'  => ! empty( $settings['duration'] ) ? intval( $settings['duration'] ) : 1000,
					'thousands' => ! empty( $settings['thousandSeparator'] ) ? $settings['thousandSeparator'] : '',
				]
			)
		);

		echo "<div {$this->render_attributes( '_root' )}>";

		if ( $prefix ) {
			echo '<span class="prefix">' . $prefix . '</span>';
		}

		echo '<span class="count">' . $count_from . '</span>';

		if ( $suffix ) {
			echo '<span class="suffix">' . $suffix . '</span>';
		}

		echo '</div>';
	}

	public static function render_builder() { ?>
		<script type="text/x-template" id="tmpl-bricks-element-dynamic-counter">
			<div
				:data-bricks-counter-options="JSON.stringify({
				countFrom: settings.hasOwnProperty('countFrom') ? parseInt(settings.countFrom) : 0,
				countTo: settings.hasOwnProperty('countTo') ? parseInt(settings.countTo) : 100,
				duration: settings.hasOwnProperty('duration') ? parseInt(settings.duration) : 1000,
				prefix: settings.hasOwnProperty('prefix') ? settings.prefix : '',
				suffix: settings.hasOwnProperty('suffix') ? settings.suffix : '',
				thousands: settings.hasOwnProperty('thousandSeparator') ? settings.thousandSeparator : ''
			})">
				<span class="prefix" v-if="settings.prefix" v-text="settings.prefix"></span>
				<span class="count">{{settings.hasOwnProperty('countFrom') ? parseInt(settings.countFrom) : 0}}</span>
				<span class="suffix" v-if="settings.suffix" v-text="settings.suffix"></span>
			</div>
		</script>
		<?php
	}
}

As far as I can tell, the intval() function in php and the parseInt() function in javascript should convert the text to a number for you automatically. Which to me suggests your code should just work. Unless of course you fail to feed it an actual number.

Have you tried using your code as is? Are there any console errors?

I’ve tried it, yes, using both a number and the dynamic field data (which is set to a number). With the number set in the text field, the code on the page actually does return a number, but the counting up animation doesn’t happen.

If I set it to the dynamic field data, then countTo returns 0, even when the number is more than 0, and the animation doesn’t happen there, either.

There is one error in the console, but I don’t know think it’s related, it happens on every page:

Hey!

Sorry I never got back to you. I didn’t know anything more to tell you. But I think you’ll be pleased to hear that Bricks 1.5.4 now supports dynamic data in the Counter Element. :wink:

Hey, thanks! Yes, Thomas was very kind and responded personally to my support request around this, then decided to just add it into the next version himself. :slight_smile:

Amazing support for a great theme!

1 Like