Closed JuGid closed 3 years ago
Hi,
Can you show the relevant code you are using please (where you remove items)? (Maybe skip the Yaml part since that is not really relevant).
AFAIK it should be possible: https://github.com/php-school/cli-menu#getting-removing-and-adding-items
Note that you need to manually redraw the menu if you do that.
Hi,
Thanks for your answer. This is the relevant code you asked. This is the function I call to build my Menu in another class file. I have removed the parts you don't need.
(ShowMenu)
public function createWithBuilder(CliMenuBuilder $mb) {
$callable = function (CliMenu $menu){;
$menu->removeItem($menu->getSelectedItem());
$menu->redraw();
};
$mb->setTitle('USELESS THINGS - SHOW');
$value = Yaml::parseFile(Task::getFileSave());
foreach($value['tasks'] as $description=>$priority) {
$mb->addItem('['.$priority.'] '. $description, $callable);
}
$mb->addLineBreak('-');
return $mb;
}
I have another menu to create my Tasks (CreateMenu) :
public function createWithBuilder(CliMenuBuilder $mb) {
$create = function (CliMenu $menu) {
$items = $menu->getItemByIndex(0)->getItems();
$items[0]->setText('Description');
$items[1]->setText('Priority');
$this->task->saveAndReset();
FlashCreator::create($menu, $text);
$menu->redraw();
};
return $mb->setTitle('USELESS THINGS - CREATE')
->addSplitItem(function (SplitItemBuilder $b) use ($askDescription, $askPriority){
$b->addItem('[D]escription', $askDescription)
->addItem('[P]riority', $askPriority);
})
->addItem('Create', $create)
->addLineBreak('-');
}
}
When I switch from Create menu to Show menu, it doesn't update my menu if I have created a new element. Should I add the Item from CreateMenu into my ShowMenu to see it ?
Sorry I don’t really understand the problem. Can you provide a minimal reproducer that I can run myself and see the problem in action?
Use the code below. Go to "Options", click on some items to delete them. "Go back" then go back to "Options". The menu is not rebuilt with all items. The deleted items still deleted. That's normal but I would like to rebuild the menu as the original.
<?php
use PhpSchool\CliMenu\CliMenu;
use PhpSchool\CliMenu\Builder\CliMenuBuilder;
require_once(__DIR__ . '/../vendor/autoload.php');
$callable = function (CliMenu $menu) {
$menu->removeItem($menu->getSelectedItem());
$menu->redraw();
};
$itemCallable = function (CliMenu $menu) {
echo $menu->getSelectedItem()->getText();
};
$menu = (new CliMenuBuilder)
->setTitle('CLI Menu')
->addItem('First Item', $itemCallable)
->addLineBreak('-')
->addSubMenu('Options', function (CliMenuBuilder $b) use ($callable){
$b->setTitle('CLI Menu > Options')
->addItem('First option', $callable)
->addItem('Second option', $callable)
->addItem('Third option', $callable)
->addLineBreak('-');
})
->setWidth(70)
->setBackgroundColour('black')
->build();
$menu->open();
Ok there is not really a good way to do this - if you remove them, then they are gone. You will either have to rebuild the menu entirely - or replace some internal actions to do it.
Here is an example replacing the Go Back
action with a custom one which will removes all your items and replaces them each time, keeping the actions in place at the bottom.
<?php
use PhpSchool\CliMenu\Action\ExitAction;
use PhpSchool\CliMenu\Action\GoBackAction;
use PhpSchool\CliMenu\CliMenu;
use PhpSchool\CliMenu\Builder\CliMenuBuilder;
use PhpSchool\CliMenu\MenuItem\SelectableItem;
require_once(__DIR__ . '/vendor/autoload.php');
$callable = function (CliMenu $menu) {
$menu->removeItem($menu->getSelectedItem());
$menu->redraw();
};
$itemCallable = function (CliMenu $menu) {
echo $menu->getSelectedItem()->getText();
};
$items = [
new SelectableItem('First option', $callable),
new SelectableItem('Second option', $callable),
new SelectableItem('Third option', $callable),
];
$goBack = new SelectableItem('Go Back', new class($items) extends GoBackAction {
private $items;
public function __construct(array $items)
{
$this->items = $items;
}
public function __invoke(CliMenu $menu) : void
{
$items = $menu->getItems();
//remove all our items except for the line break and actions
foreach ($this->items as $item) {
if (in_array($item, $items, true)) {
unset($items[array_search($item, $items, true)]);
}
}
//prepend all our items to the remaining actions and add replace all items
$menu->setItems([...$this->items, ...$items]);
parent::__invoke($menu);
}
});
$menu = (new CliMenuBuilder)
->setTitle('CLI Menu')
->addItem('First Item', $itemCallable)
->addLineBreak('-')
->addSubMenu('Options', function (CliMenuBuilder $b) use ($items, $goBack) {
$b->setTitle('CLI Menu > Options')
->addMenuItem($items[0])
->addMenuItem($items[1])
->addMenuItem($items[2])
->addLineBreak('-')
->disableDefaultItems()
->addMenuItem(new SelectableItem('Exit', new ExitAction))
->addMenuItem($goBack);
})
->setWidth(70)
->setBackgroundColour('black')
->build()
->open();
This solved my problem ! Thank you !
Hello,
I'm making a task manager with CLI-menu. To achieve that I use a plain text Yaml file to store tasks. I can delete some tasks and remove the Item that comes with. When I 'Go back' then return to my SubMenu with my tasks, the list is not up-to-date because the builder is not recalled. (if I delete a task from Items, it still deleted since I rerun the app).
Is it possible to add something to achieve that or is there something already ?
Edit : I put the code in a GitHub repository if my explanation aren't good enough...