Writing value of FormGroup FormControls in Angular - formarray

I have an array of FormControls in an inventory application in which I am trying to update a single item in the form based on a change - by another user on another device - in the value in the back end. (Firebase in my case.)
I have access to the FormControl and I am able to make that change... except not. Here's the situation:
You'll not from the console output, that when I expand the FormGroup and look at the value I see 3. This is the correct value from the back end. But the FormGroup.controls.current.value is still 4... the old value in the form.
I've been trying to play with different methods of accessing this control to get it to update properly.
Here's the code:
this.items.controls.forEach((item, index) => {
if (item.value.current != this.inventoryElements[index].current) {
//First attempt to change the value of the formControl
this.items.value[index].current =
this.inventoryElements[index].current;
//Second attempt
this.items.controls[index].value.current =
this.inventoryElements[index].current;
//Third attempt
item.value.current = this.inventoryElements[index].current;
console.log(this.items.controls[index]);
console.log(this.items.controls[index].value.current);
console.log(this.items.value[index].current);
}
});
this.inventoryElements[index].current holds the value I want to put into the form control.
this.items is the array of Form Controls.
You can see that I made three attempts to get the value there without luck -
The first console.log results in 4.
The second console.log results in 4.
The third console.log results in the output pasted at the top of this question.
One more piece of background. The FormArray is this {current: string, notes: string} and my attempt was to modify the current value.
By the way, the reason I'm going through all of this mess is that I was unhappy that an update of a single value in the back end would cause the entire page to reload. So this was an attempt to see whether I could update a single value and avoid the whole page reload.
Thanks the the help.
Paul

The third attempt was close. Instead of assigning the value with an equals sign:
item.value.current = this.inventoryElements[index].current;
Use patchValue
item.patchValue({
current: this.inventoryElements[index].current});

Related

JavaScript: how to trigger update form after setting input

I am writing a simple App Inventor program to populate a Covid-19 school health check page. I am stuck on selecting a school. Normally you type in a school name, the page finds string matches and you select from the list of string matched school. I am able to simply set the field manually but the rest of the form doesn't update. I know I must trigger an update but I cannot make head or tails of how this page works.
image of school selection
typing in part of school name
From the Chrome console I can do the following:
x = document.getElementsByClassName("k-textbox")
x[1].value = "Horace"
From the picture you can see the text was updated to "Horace" but the results have not updated. What should I do to force an update so the results list shows proper matches? Also, how do I query the matching results so I can confirm that my input was explicit enough to return a single match? FYI, this form entry page will be hidden to the user.
You can get the kendoDropDownList, call the read method from it's dataSource, and pass the locationName value of what you want. This won't set the text in the textbox, but it will filter your list down like you want.
To test, click on the input, open your console, and run the following:
$('#Location').data('kendoDropDownList').dataSource.read({ locationName: 'horace' })

Dusk: Loop on class of inputs can't enter text with sendKeys

I'm not able to enter text into a specific input box as determined by a data attribute. There could be dozens of inputs with the same class, so I'd prefer not to add dusk='xxxx' all over the page.
For route and server-side efficiency, the AJAX function pulls a type from the array of inputs and routes to a function that branches the action.
Blade code:
{!! Form::text('question[]', null,
['class'=>'form-control actionChange', "data-id"=>$question->id, "data-type"=>'question']) !!}
The page starts with other questions with a different type, so I have tried using nth-child(x) to grab the selector within the modal, but no success. I've tried using $browser->script() as well.
Reading several similar questions, such as this one, it appears that a loop within the modal is likely the best way to go. This method correctly assigns the selector to the loop variable, $input. It correctly clear()s data, and I've tested similar code with click() and it successfully works. However, it will not enter data in the input. type() and keys() don't appear to work with the RemoteWebElement, so I believe my only choice to enter data is sendKeys().
Dusk test code:
$browser->assertPathIs('/notice')
->whenAvailable('.modal', function($modal) use($browser) {
$modal->assertSee('Survey for:')
->waitFor('#heading')
// WORKS fine
->keys('#heading', 'Edited Heading for Survey', '{enter}')
->waitFor('.actionSurvey');
// Edit a question -- NOT WORKING
foreach ($browser->elements('.actionChange') as $input) {
$dataType = $input->getAttribute('data-type');
if($dataType === 'question') {
$input->clear() // WORKS Fine
->sendKeys('Edited_Question') // NOT successful
break;
I've tried with and without the clear() method, as well as various selector choices both within and out of the modal loop. Same for script() Also, tried using the $modal variable to get the elements, but this was just a guess as I'm a bit out of my depth of understanding at this point.
I probably fubar'd something basic, but I don't understand why one method works, and another doesn't on the same handle.

CAPL on sysvar_change procedure with sysvar of custom struct data type

according to the manual,
The procedure on sysVar is called only when the value of the variable
changes. It can also be written as on sysVar_change. If you want to be
notified of value updates to the variable which don’t change the
value, you should use on sysVar_update instead.
In my example scenario, I have a system variable s::sysv of custom Struct Data Type X, where X has two fields: A and B.
In my CAPL script I put the following:
on sysvar_change s::sysv.A
{
// do stuff
}
Expected output is to do stuff only when s::sysv.A changes. However, since s::sysv.B is often updated when my simulation is running, then the procedure on sysvar_change s::sysv.A is called a lot more times than I expect, even if A doesn't change its value.
I don't understand why, and I'm putting a lot of workaround in place to avoid this, can anybody help?
Edit:
according to one reply, the event handler is not the struct element, but still the variable. However, the keyword this is now pointing to the struct element and not to the variable.
This bit of the manual is also relevant:
You can also react in the same way to value changes of specific
elements of a system variable of type struct or generic array. For
this, add the element to the name of the variable.
I have tried this functionality in the latest CANoe and it works as expected. The following is my code.
on key 'a'
{
#sysvar::Var_Struct1.StructMem1++;
}
on key 'b'
{
#sysvar::Var_Struct1.StructMem2++;
}
on sysvar_change Var_Struct1.StructMem1
{
write("StructMem1 value changed");
}
on sysvar_change Var_Struct1.StructMem2
{
write("StructMem2 value changed");
}
Whenever I press the key 'a' or 'b', the corresponding event is triggered.
Your variable is s::sysv. The event handler is called whenever the value of the variable changes. No matter whether A or B changes.
There is no way to restrict it only to certain changes of the value.
This is similar to the fact that you can also not be notified when, e.g. only the 3rd bit of an integer changes.
To me, it seems best to reconsider your setup and ask yourself, whether using the struct is the right approach, or whether it might be better to use two separate system variables A and B.

request.object.previous() is not working in beforeSave()

I'm trying to check the current and previous value of an attribute in the beforeSave(). So i tried to use request.object.previous("attribute_name") but it is still returning the current changed value. Although the .ditry() is returning TRUE which means that the value is changed. Any idea what is wrong here ? I appreciate your feedback.
I think the .previous() isn't actually part of the Parse.com sdk, but simply inherited from backbone.
In a beforeSave handler, I have something like:
if(object.dirty("attr")) {
console.log("After: " + object.get("attr") + ", Before: " + object.previous("attr")); }
The value returned by 'previous' is always the same. Is this functionality actually
implemented? I've seen a few threads elsewhere that imply it's not -
if so, can you remove it from the API docs until it's done?
If it doesn't work, is the correct workaround to query the previous
object? Or does 'changedAttributes' work?
Oh, I now see that 'previous' is some cruft from Backbone.
source1
previous is a method inherited from Backbone.Model. It won't return the previous value of a field in Cloud Code.
source2
Might not be the answer you're looking for, so as a way to workaround the lack of the .previous implementation this this out:
Don't know if this is helpful or if it would be considered too costly
of a workaround, but you could add a column to the object that is
being updated that stores the previous value of the original column.
This would allow you to access the previous value in the AfterSave
function.

apex retrieve default item value

Is it possible to get default item value using plsql? I have a validation and in case it fails I want to reset item to its default value.
I tried using apex_util.set_session_state('P_ITEM_NAME', null) but that did not have any noticeable effect.
How can default item be retrieved or item itself be reset?
When creating a page process, there is a condition called "Inline validation errors displayed", maybe this will help? In this process you can reset items to null, then when page loads, item values will return to their default values.
UPD:
Create process:
Process Point: On Load Before header
Condition: Inline Validation Errors Displayed
Process source:
begin
for i in (
select t.ITEM_DEFAULT, t.item_name
from apex_application_page_items t
where t.application_id = :APP_ID
and t.page_id = :APP_PAGE_ID
) loop
apex_util.set_session_state(i.item_name, i.item_default);
end loop;
end;
This will return all page items to their default values.
This solution some ugly, but i don't know another solution for this problem.
:P_ITEM_NAME := null;
The difference here is the ":" infront of the item. Using it like this will give access to the item. Using apostrophes isn't needed I believe.
If this doesn't work with your version try without the ;.
So you can use:
:P_ITEM_NAME
To get the value.
I could not find any function that would return me default value using an item. However I could use default item setting to mimic this. Page processes do not run when page has validation errors, so I added conditional page process that performs the same checks as my validation and when these checks indicate that validation fails it just clears item state.
This is ugly as it requires checks to be duplicated and it seems that it is necessary to replicate almost same page controls through all pages where such reset mechanism is necessary.

Resources