how to use callback class?

Notice: This thread is very old.
thcom
Backer | 94
+
0
-

hi i try to use DependentSelectBox in my project,

i dont like this structure, it is not pretty to read and to understand for me :(

<?php
		$form->addDSelect('select2', 'Select 2', $form['select1'], function($form) {
			$v = $form['select1']->getValue();
			return array("$v 1" => "$v 1", "$v 2" => "$v 2", "$v 3" => "$v 3");
		});
?>

i prefer something like

<?php

	public function MyCbFunc($form) {
			$v = $form['select1']->getValue();
			return array("$v 1" => "$v 1", "$v 2" => "$v 2", "$v 3" => "$v 3");
		}

	$myCallBack = new Nette\Callback(array($this, '$this->getData', $form)); // not right code

	$form->addDSelect('select2', 'Select 2', $form['select1'], $myCallBack);
?>

but i have problem how to righct declare the function MyCbFunc anfd how to right create a callback :(

i try many variants, but nothing was working well

thx
Tomas

Last edited by thcom (2013-05-22 14:33)

llook
Member | 407
+
0
-
$myCallBack = new Nette\Callback($this, 'getData');

Or:

$myCallBack = callback($this, 'getData');

And note the method has to be public. The argument ($form) is passed when the callback is called.

Majkl578
Moderator | 1364
+
0
-

The usage then seems to be obvious, doesn't it? :)

$callback = new Nette\Callback($obj, 'method');
$result = $callback($someArg);
thcom
Backer | 94
+
0
-

great, thanks its working,
i have a mistake with parameter

i still don't know, how the callbacka functions knows, that as the parametr passes the $form variable …

Majkl578
Moderator | 1364
+
0
-

In this case, it's being passed automatically in Form using an event (array of callbacks), see Form::fireEvents(). In other cases, you pass it when you invoke the callback, as in my example above, which presumes method having one argument.

thcom
Backer | 94
+
0
-

yes!, i understand, but what to do, when i need my own parameter in callback function

when i use this :

<?php
		$form->addDSelect('zbozi', 'Zbozi:', $form['kategorie'], $myCallBack(1));
?>

the $form parameter is replaced by constant 1

when i use

<?php
	$form->addDSelect('zbozi', 'Zbozi:', $form['kategorie'], $myCallBack($form, 1));
?>

the parameters are given right, but i get error callback is not callable :(

Last edited by thcom (2013-05-23 21:37)

Majkl578
Moderator | 1364
+
0
-

Not sure what you're trying to do, but you can't set some parameters before you actually call the callback. The only way would be to wrap it in e.g. closure. In your latest code, you invoke the callback instead of just passing it (what seems to be your intention). Be more specific about your goal, we don't know what you're trying to do nor what addDSelect is.

thcom
Backer | 94
+
0
-

addDSelect is a part of dependentselectbox library, see my first post

now, one pair of dependent selectboxes is working, thanks to you advices

but i need a set of them, so i need index them like

<?php
$form->addDSelect('zbozi_01', ...
$form->addDSelect('zbozi_02', ...
$form->addDSelect('zbozi_03', ...
?>

this code i can create, but problem is, that in callback function (which loads data in second selectbox) i need a parametr – link to parent select box

<?php
    public function MyCbFunc($form) {
            $v = $form['select1']->getValue();
            return array("$v 1" => "$v 1", "$v 2" => "$v 2", "$v 3" => "$v 3");
        }
?>

there i need replace select1 with zbozi01, 02 … 03, so i need another parametr

i hope, i explain it well

Majkl578
Moderator | 1364
+
0
-

but i need a set of them

If you need a set of something repeating, you should use container, not add index into name. So say we want zbozi three times, it'd look like this:

$zboziContainer = $form->addContainer('zbozi');
for ($i = 1; $i <= 3; $i++) {
     $zboziContainer->addDSelect($i, 'Zbozi' . $i . ':', $form['kategorie'], $myCallBack);
}

And then you can access the control's instance like $form['zbozi'][1].

problem is, that in callback function (which loads data in second selectbox) i need a parametr – link to parent select box

According to source, you receive an instance of DependentSelectBox itself as second argument. So your callback should look like this:

public function MyCbFunc(Container $container, DependentSelectBox $dSelectBox) {
    $v = $dSelectBox->getValue();
    return array("$v 1" => "$v 1", "$v 2" => "$v 2", "$v 3" => "$v 3");
}

(Note that container is acutally an instance of form, but this way it's more generic.)

But to answer your original question, if it was not possible to the above way, you would have to do it other, smelly way, here is one option – wrap your callback into another one:

$zboziContainer = $form->addContainer('zbozi');
for ($i = 1; $i <= 3; $i++) {
     $zboziContainer->addDSelect($i, 'Zbozi:', $form['kategorie'], function (Container $container) use ($myCallBack, $i) {
    $myCallBack($container, $i); // note how we're passing $i through closure to our own callback
});
}

// ...

public function MyCbFunc(Container $container, $dIndex) {
    $v = $containerdSelectBox['zbozi'][$dIndex]->getValue();
    return array("$v 1" => "$v 1", "$v 2" => "$v 2", "$v 3" => "$v 3");
}

No doubt there are other ways, but this was just to imagine.

thcom
Backer | 94
+
0
-

many thanks, containers looks very good

but i have last(i hope) problem

i need both selects in this container, for example 5 rows and on every row is kategorie select and zbozi dselect

<?php
		$kategData = $this->getKategData(); // load data for select
		$zboziContainer = $form->addContainer('zbozi');
		for ($i = 1; $i <= 5; $i++) {
			$zboziContainer->addSelect($i, 'Kategorie' . $i . ':', $kategData);
			$zboziContainer->addDSelect($i, 'Zbozi' . $i . ':', $form['kategorie'], $myCallBack);
		}

?>

problem is how to link dselect to master select, the third param in AddDSelect < $form[‘kategorie’] >

Majkl578
Moderator | 1364
+
0
-

Your example wouldn't work since there can't be two components (select and dselect here) with same name. So we need to go deeper ™ and a) add one more nested container or b) name each select uniquely. I'd prefer a) variant since it's much cleaner, so here it is:

$kategData = $this->getKategData(); // load data for select
$zboziContainer = $form->addContainer('zbozi'); // first level - container for repeated content
for ($i = 1; $i <= 5; $i++) { // second level - we'll add a container of two selects 5 times
	$zboziItemContainer = $zboziContainer->addContainer($i); // third level - just because we have more than one repeated element
	$zboziItemContainer->addSelect('category' 'Kategorie' . $i . ':', $kategData);
	$zboziItemContainer->addDSelect(
		'item',
		'Zbozi' . $i . ':',
		$zboziItemContainer['category'], // equivalent to $form['zbozi'][$i]['category']
		$myCallBack
	);
}

At first, it might look strange, but it has a logical reason. Because of this nesting, the resulting structure makes clear sense, it will look like this:

form
-zbozi
--1
---category
---item
--2
---category
---item
...

In the above code, note I also answered your question:

problem is how to link dselect to master select, the third param in AddDSelect < $form[‘kategorie’] >

Hope it solves your problem. :)

thcom
Backer | 94
+
0
-

its great, many thanks, everything is working now !