Executing a command from another command - reactiveui

I have a 'hello world' form (Xamarin forms) with some fields and a submit button. There's an observable (CanSave) which controls when the SaveChangesCommand can execute. If the save button is pressed when the CanSave is false, I want to a display a message to the user.
With the code below, if I
enter incorrect data
click save (the error message shows)
then correct the data.
CanSave becomes true and SaveChangesCommand is executed - before the button is hit again. It's as though the previously blocked button press was queued until canExecute became true.
What am I missing?
Thanks :-)
public PersonalProfileModel()
{
this.SaveChangesCommand = ReactiveCommand.CreateAsyncTask(this.CanSave(), message => this.doAllThings(message as string));
this.ButtonClickedCommand = ReactiveCommand.Create(Observable.Return(true));
this.ButtonClickedCommand.InvokeCommand(this.SaveChangesCommand);
// ButtonClickedCommand.Subscribe(x => this.SaveChangesCommand.Execute("hello")); // tried this too
}
public ReactiveCommand<object> ButtonClickedCommand { get; set; }
public ReactiveCommand<string> SaveChangesCommand;
public IObservable<bool> CanSave()
{
var fieldsValid = this.WhenAnyValue(
x => x.Name,
x => x.Country,
(f1, f2) =>
f1 == "a"
&& f2 == "b");
return fieldsValid;
}
public Task<string> doAllThings(string message)
{
var result = Task.Run(() =>{return "hello " + message;});
return result;
}

How about this:
this.SaveChangesCommand = ReactiveCommand.CreateAsyncTask(
this.CanSave(),
message => this.doAllThings(message as string));
this.ButtonClickedCommand = ReactiveCommand.CreateAsyncObservable(
SaveChangesCommand.CanExecuteObservable.StartWith(true),
x => SaveChangesCommand.ExecuteAsync(x));
Now we're explicitly describing the relationship between the ButtonClicked's Command in terms of the SaveChangesCommand - "The ButtonClicked command is enabled when SaveChanges can be executed"

This turned out to be a misunderstanding in the behaviour of ReactiveCommands and canExecute.
See ReactiveCommand not respecting canExecute

Related

Laravel help for optimize command script

I'm working with Lumen framework v5.8 (it's the same as Laravel)
I have a command for read a big XML (400Mo) and update datas in database from datas in this file, this is my code :
public function handle()
{
$reader = new XMLReader();
$reader->open(storage_path('app/mesh2019.xml'));
while ($reader->read()) {
switch ($reader->nodeType) {
case (XMLREADER::ELEMENT):
if ($reader->localName === 'DescriptorRecord') {
$node = new SimpleXMLElement($reader->readOuterXML());
$meshId = $node->DescriptorUI;
$name = (string) $node->DescriptorName->String;
$conditionId = Condition::where('mesh_id', $meshId)->first();
if ($conditionId) {
ConditionTranslation::where(['condition_id' => $conditionId->id, 'locale' => 'fr'])->update(['name' => $name]);
$this->info(memory_get_usage());
}
}
}
}
}
So, I have to find in the XML each DescriptorUI element, the value corresponds to the mesh_id attribute of my class Condition.
So, with $conditionId = Condition::where('mesh_id', $meshId)->first(); I get the Condition object.
After that, I need to update a child of Condition => ConditionTranslation. So I just get the element DescriptorName and update the name field of ConditionTranslation
At the end of the script, you can see $this->info(memory_get_usage());, and when I run the command the value increases each time until the script runs very very slowly...and never ends.
How can I optimize this script ?
Thanks !
Edit : Is there a way with Laravel for preupdate multiple object, and save just one time at the end all objects ? Like the flush() method of Symfony
There is a solution with ON DUPLICATE KEY UPDATE
public function handle()
{
$reader = new XMLReader();
$reader->open(storage_path('app/mesh2019.xml'));
$keyValues = [];
while ($reader->read()) {
switch ($reader->nodeType) {
case (XMLREADER::ELEMENT):
if ($reader->localName === 'DescriptorRecord') {
$node = new SimpleXMLElement($reader->readOuterXML());
$meshId = $node->DescriptorUI;
$name = (string) $node->DescriptorName->String;
$conditionId = Condition::where('mesh_id', $meshId)->value('id');
if ($conditionId) {
$keyValues[] = "($conditionId, '".str_replace("'","\'",$name)."')";
}
}
}
}
if (count($keyValues)) {
\DB::query('INSERT into `conditions` (id, name) VALUES '.implode(', ', $keyValues).' ON DUPLICATE KEY UPDATE name = VALUES(name)');
}
}

How to stop formflow dialog from re-prompting user when validation fails?

I have a formflow dialog in which one of it's properties is this...
[Describe("Car Mileage")]
[Prompt("Cool! What's the mileage of the car?")]
[Template(TemplateUsage.NotUnderstood, "Sorry, I didn't understand that mileage value. Can you enter it again please?")]
public string Mileage { get; set; }
Ignore the [Template(TemplateUsage.NotUnderstood,... for now, I'll come back to that.
The dialog is built using the following...
var form = builder
.Field(new FieldReflector<CarValuationDialog>(nameof(ValuationOption))
.SetPrompt(new PromptAttribute($"Hi.<br /><br />Are you looking to get a value for a car you're selling, or car you're buying? {{||}}")))
.Field(new FieldReflector<CarValuationDialog>(nameof(RegistrationNumber))
.SetDefine(RegistrationNumberDefinitionMethod))
.Field(new FieldReflector<CarValuationDialog>(nameof(Mileage))
.SetValidate(async (state, value) =>
{
var result = new ValidateResult { IsValid = true, Value = value };
var regex = new Regex("[0-9,]+");
var match = regex.Match((string)value);
if (match.Success)
{
result.IsValid = true;
}
else
{
result.Feedback = "Sorry, I didn't understand that.";
result.IsValid = false;
}
return await Task.FromResult(result);
}))
.Field(
nameof(PreviousOwnerOption),
active: carValuationDialog => carValuationDialog.ValuationOption == ValuationOptions.LookingToSell)
.Field(
nameof(ServiceHistoryOption),
active: carValuationDialog => carValuationDialog.ValuationOption == ValuationOptions.LookingToSell)
.Confirm(Confirmation)
.OnCompletion(GetValuationAndDisplaySummaryToUser);
return form.Build();
This question is related to
`Feedback` text not shown in bot conversation
I'm experimenting with the validation for Mileage, as I've changed that property from int to string in order to allow freeflow text e.g. "23,456 miles". As a side-effect of changing the data type, when the validation for Mileage fails, I get the following...
Not only does the result.Feedback value now get shown to the user (it did not before, when Mileage was an int), which is fine, but also the original question text is shown.
So my main question is - what can I do so that when validation fails, the original question prompt is not shown to the user?
As a side note, when changing Mileage back to int, and the validation fails (result.IsValid = false), result.Feedback is not shown, but [Template(TemplateUsage.NotUndderstood.... is now shown. So it seems the type of the property matters in relation to what validation messages are shown.

in Gigya, Unable to set attribute in "email" of Screen "Forget Password" in Screen-sets ID "Default-LinkAccounts"

I have the following js implemented in Gigya JavaScript Parameters:
onAfterScreenLoad: function(event) {
if ((ell = document.querySelector("#gigya-forgot-password-screen input[type=text][name=loginID]")) != null){
ell.setAttribute('type', 'email');
ell.setAttribute('placeholder', 'user#example.com');
ell.setAttribute('autocomplete', 'off');
}
},
I am able to use the above code to handle the fields of all other screen-sets EXCEPT this "Forget Password" screen (i.e. Screen ID: gigya-forgot-password-screen) in Screen-sets ID "Default-LinkAccounts".
It looks like the forgot password flow is triggered without a user session and independently of the information passed into the Email field on the login screen.
If it is, then how to implement this.
it seems the name of the field is different depending upon which screen you are using:
window.ell = document.querySelector("#gigya-register-screen input[type=text][name=email]");
window.ell = document.querySelector("#gigya-login-screen input[type=text][name=username]");
window.ell = document.querySelector("#gigya-forgot-password-screen input[type=text][name=username]");
so:
onAfterScreenLoad: function(event) {
var ell = null;
if ((event.currentScreen === "gigya-forgot-password-screen") || (event.currentScreen === "gigya-login-screen")) {
ell = document.querySelector("#" + event.currentScreen + " input[type=text][name=username]");
} else if (event.currentScreen === "gigya-register-screen") {
ell = document.querySelector("#gigya-register-screen input[type=text][name=email]");
}
if (ell != null){
ell.setAttribute('type', 'email');
ell.setAttribute('placeholder', 'user#example.com');
ell.setAttribute('autocomplete', 'off');
}
}

Require a field only if a checkbox is checked CakePHP 2 Validation

Heres the problem
I want to require a field (litters_per_year) only if another field that is a checkbox is checked. When I do this, cake is trying to force me to put a value into the field and I don't know why. I have tried setting required & allowEmpty to false & true respectively, but then my custom rule does not run.
Heres the code
NOTE: The details of the following code aren't that important - they are here to provide a scenario.
I have the following code in my VIEW which works fine:
echo $this->Form->input('litters_per_year', array(
'label' => 'Litters per year (average)'
));
I have the following code in my MODEL's public $validate:
'litters_per_year' => array(
'isNeeded' => array(
'rule' => array('isNeeded', 'litters_per_year'),
'message' => 'Please enter the litters per year average'
)
)
which is calling the custom validation method
public function isNeeded($field) {
// Check if a checkbox is checked right here
// Assume it is not... return false
return false;
}
It returns false for simplicity to solve this issue.
Let's assume that the checkbox field is named 'the_checkbox'.
At the moment your field should always fail validation, since you return false from isNeeded.
To make it work as you expect, do something like this:
(Note: replace 'ModelName' with your model name)
public function isNeeded($field) {
if ($this->data['ModelName']['the_checkbox']) {
// Checkbox is checked, so we have to require litters per year
if (empty($field)) {
// They have checked the box but have NOT entered litters_per_year
// so we have a problem. NOT VALID!
return false;
} else {
// They have checked the box, and entered a litters_per_year
// value, so all good! Everything is valid!
return true;
}
} else {
// Checkbox is not checked, so we don't care what
// the field contains - it is always valid.
return true;
}
}
Or, without the needless verbosity, this should work:
public function isNeeded($field) {
if ($this->data['ModelName']['the_checkbox']) {
return $field;
} else {
return true;
}
}
In this example, if the checkbox is checked, validation will pass if $field is truthy, and fail if it is falsey.

data validation on prompt Input box on Windows Phone

RadInputPrompt.Show("Enter the number", MessageBoxButtons.OK, message, InputMode.Text, textBoxStyle, closedHandler: (arg) =>
{
int okButton = arg.ButtonIndex;
if (okButton == 0)
{
//do some check before submit
if (string.IsNullOrEmpty(arg.Text))
{
MessageBox.Show("Please input the number.");
return; //??
}
//submit
}
else
{
return;
}
});
My question is :
I do some data validation (for example: numeric only, the digit count...) before submit
If the input from user is invaild, I hope the Prompt Input Screen can still remain.
If I use "return" keyword, it'll go back to the main screen.
Or is there any other ways of validation (something like AJAX?) that I can use on this prompt sceen rather than do it on code-behind page?
Thanks a lot!
One technique is to just keep looping and showing the input prompt each time the user clicks OK, but fails to satisfy the input validation. You can see an example of this below with the input text box continuing to repeat if the result is not a valid numeric value.
It's also a good idea to add some kind of feedback to the user indicating that the previous input was not acceptable in the event of an invalid submission. An example of this is below where the title of the input text box is changed after the first invalid submission to include text indicating that the input value must be a valid number.
NOTE: Telerik is saying the ShowAsync method should now be used instead of the Show method since it is being deprecated.
string userInput = string.Empty;
int okButton = 0;
bool firstPass = true;
double numericResult;
while (okButton.Equals(0) && string.IsNullOrWhiteSpace(userInput))
{
string inputBoxTitle = (!firstPass) ? "Enter the number (you must enter a valid number)" : "Enter the number";
InputPromptClosedEventArgs args = await RadInputPrompt.ShowAsync(inputBoxTitle, MessageBoxButtons.OKCancel);
okButton = args.ButtonIndex;
firstPass = false;
if (okButton.Equals(0))
{
if (!string.IsNullOrWhiteSpace(args.Text))
{
bool isNumeric = double.TryParse(args.Text, out numericResult);
if (isNumeric)
{
// We have good data, so assign it so we can get out of this loop
userInput = args.Text;
}
}
}
}

Resources