dependent() not setting new value
dependent() not setting new value
Hi.
Per the example of the documentation in dependent()
, I wrote something like:
editor.dependent('field1', function (val, data, callback, e ) {
// Check if field data has changed.
// (Is it intended to check this? Because otherwise this block works at all times even if field1 is not modified.)
if (data.row.field1 != data.values.field1)
editor.field('field2').set('some value');
callback(true);
});
field2
is never set. I confirmed that it steps into the if
condition by logging the "some value" into the console in the if block, but never sets the value for the field. I also tried assigning data.values.field2
manually to "some value" to still no use.
By the way I saw that some other people asked the same question before but none are answered. I resolved the problem with another approach like this for now:
editor.on('preSubmit', function (e, json, action) {
// Detect which row is being edited.
let row_id = Object.keys(json.data)[0];
// Detect if the edited cell is we want to write a dependent for.
if (action == 'edit' && editor.display() == 'inline' && editor.displayed()[0] == 'field1') {
// Do some calculations here..
// And alter the json data object directly before sending to server.
json.data[row_id].field2 = 'some value';
}
return !editor.inError();
});
Answers
Something else must be wrong with your code, I guess. I use "dependent" all the time to set variables, message texts retrieved from the server etc. Here is an example that handles an array of two variables at the same time:
And the functions used:
Thank you for taking time to reply. I think there are two fundamental points I would like to talk about in your post.
callback(true);
for the dependency to let the editor continue.)field().set()
is a very core API method of the editor. For this not to work, I must have broke a very vital part of it; which shouldn't be the case as there are many customizations and the core work pretty good.Now interestingly, I tried it without any conditioning (which I am sure was working, because I could log the val in that if block to console), now it works but with a possible bug.
Now the possible bug I mention here is,
field2
is set whetherfield1
succeeds or not. I mean there are some custom validators on both fields. Even iffield1
fails in one of the validators,field2
is set successfully. Should it really? Why doesn't it regard the result of its dependency? Maybe it is by design, but we should reconsider the meaning of the word "dependent" here. Maybe I should file a bug report?And another note here; I still need those conditions to see if the value of
field1
is changed. Because I have some validators integrated to 3rd parties set forfield2
. So if nothing has changed infield1
, the validators forfield2
shouldn't fire. But it does.I was curious about this so I just tried it out and it seems to work as expected: http://live.datatables.net/jorutoji/25/edit .
Click a row and edit it. Then change the "Name" field value and tab or click out (to trigger a
change
event) and the Salary field will correctly update.If my little example and @rf1234's code doesn't help, could you link to a test case showing the issue or modify the example to demonstrate the issue please?
Thanks,
Allan
Thanks Allan. In your test instance, I edited the name but the salary field didn't set. I don't get how it is working? See your example, I edited the name field but salary still has the old value and not the new value you set through
dependent()
Edit: Alright, now I understand what you mean but I think this is a very unreliable way. If you edit the name and hit "Save" button, it doesn't work. You have to click somewhere else to trigger the change as you said. But I think this is very wrong, don't you think? I mean clicking on save button doesn't trigger the change and so it doesn't set the value.
Edit the name then go to another field by clicking in it or tabbing. You should see the Salary change to
55555
. Does it not change for you?Kevin
It changes, but I think it shouldn't work this way. You shouldn't be telling all of your users "to click somewhere else before saving", should you?
Plus, as I said before,
dependent()
sets the new value even if the the field which it depends on doesn't pass validation. I humbly thinkdependent()
needs a complete rework with a different logic.Edit: I mean:
1- It should regard whether if the field which we depend on passes the validation and is successfully sent to server. It doesn't regard whether that field fails or passes now.
2- It should work whether you click somewhere else or not. It works only when you trigger the change intentionally. This is not viable and you can't expect end-users to know and apply these technical expectations.
3- It shouldn't trigger if there is no change. It triggers now.
Check the code I gave in my first post, that I use instead of
dependent()
. It regards the field's validation before it sets the value of the other cell. It works without expecting to trigger the change manually. And it doesn't trigger if there is no change in the field's data.Second edit: My code doesn't regard the field's validation either. I thought it did becuase I use the same validator for both of the fields. So if one of them can't pass, the other likely fails too. So this problem remains unsolved.
I see. It seems there is an issue if a change is made to the name and enter is hit. The dependent code runs but the field value doesn't seem to be update. All other cases, click update or move to another field, the field is updated. I updated the test case (with console.log) to show this issue, you can see it executes the
editor.field('salary').val(55555);
statement but its not set. @allan will need to comment on this.In Allan's test case I can edit a row not make a change and click update, move to another field or hit enter and no changes are made. Can you provide the steps to show this problem?
Kevin
You can add additional events here, too, such as
keyup
. This is Allan's example, modified to use bothkeyup
andchange
- http://live.datatables.net/bugavolo/1/editThat seems to be nearer to what you're looking for.
Colin
Now here is another news, as you noticed, on the test case, if you change the name and click "Update" button with the mouse, then dependent sets the value for the other field, but instead of clicking the button, if you press enter key to save, now dependent doesn't work.
For the other problem, we can't add server side script to the test case, so I can't show you on it. But to test it simple add a
minNum()
validator on a field and writedependent()
to depend on this field. Now type an alphanumeric value to this field and try to save. It will fail giving you this message; "input not valid". But in the mean time, dependent will still work. Of course you can say that the developer should do the checks before saving anything independent()
BUT the developer would never know if that field which we depend of failed or passed the validation.@collin yeah I had done it that way before. But as I said, I have my dependency connecting to a 3rd party integration site. I just can't send post incomplete data to 3rd party every time you fire
keyup
event.In my honest opinion again,
dependent()
logic needs to change. Because this way, it is not really depending.I'm not quite sure what you are looking for in that case. If you don't want it to trigger on every keystroke, but you need it to happen more frequently than the
change
event. Do you just want to have it lookup the value on submit? In which case your original solution of usingpreSubmit
would be the correct way to do it.I might have misunderstood - if you could clarify please, that would be great.
Thanks,
Allan
@allan I do have a question. In your test case the Salary field is not updated if I update the name and just hit enter. I added a console.log statement to show that the
editor.field('salary').val(55555);
statement executes but the update is not there. Is this expected?http://live.datatables.net/jorutoji/26/edit
Kevin
In fact as I told before, in my opinion
dependent()
as it name suggests should really be "dependent". Like;1- It should regard the validation of the field it depends on. Right now, it doesn't regard it and it runs the code block even if that field fails to validate. This way, it actually wouldn't have depended on that field. I mean if it is going to run that code block at all times anyway, without depending on that field, then why need it and call it "dependent"? As far as I can see, there is also no way that developer could know if the validation of the field we are depending on failed or passed.
2- As I said before (like in @kthorngren's live instance), submitting the editor with enter button doesn't trigger
dependent()
. (Hence it is not reliable in inline editing mode either.) We shouldn't be expecting the end-user to understand and regard all this tech stuff and triggerchange
consciously. Sodependent()
should be triggering in a way likepreSubmit
does, without the need of end-user's conscious behavior.3- Developer shouldn't need to check if there is a change of value. Rather
dependent()
should run only when something has changed. Because if I am depending on a field, that already means I would like to do some operation only when something has changed in the data I am depending on. But right now,dependent()
runs the code block even if nothing has changed.I am also following this discussion with great interest. This is my opinion on the points made above.
1 - Field validation: I don't see any client side field validation in your code. What is your suggestion on how this should work in conjunction with "dependent" (Never an issue for me: I only do field validation server side. In addition: I only use "dependent" in conjunction with dropdowns and checkboxes. I don't have a single use case where "dependent" makes sense in conjunction with a free text field.)
2 - Using "dependent" with dropdowns and checkboxes exclusively avoids this issue. No difference between either way of submission. And no need to click "outside" the changed field after changing it. That is done implicitly if you will after choosing from a dropdown or clicking a checkbox.
3 - this point has been bothering me as well - but I got used to it and learned to live with it. And now: If it was changed to a more "reasonable" fashion I might even run into issues: I am relying on the fact that "dependent" is being executed on "open" as well ...
@kthorngren
Kind of... The reason for it is that the
blur
event is async - so it is actually happening after the form submission, which happens on the click event (which then triggers the blur event after that!)."Fixing" that isn't going to be trivial. We might need to trigger a change event on all fields that have a dependent value, before submission, but this has two problems - it makes the submit async (possibly not an issue for the button since that itself is an async action triggered by the end user), and it might also cause unneed processing such as an ajax call, depending on what the
dependent()
does.@pisisler I think the issue is knowing when the value has "changed". By default we listen for the
change
event (which the browser will trigger on blur when the value has changed) - for text inputs that can be changed tokeyup
(which is obviously no use forselect
elements).I absolutely see the issue here - thanks for the clarification. I need to have a think about how we can implement a solution for this.
Allan
@rf1234 , no I don't have client-side validators, I am using server-side validators just like you do.
@allan , I think it is still not depending on a
change
, because the code block independent()
always run, whether there is a change or not. And this means it runs even if there is no change during the submission of the form.Maybe I should explain my use case to give better idea.
I have a price field (let it be price1) which is integrated to a third party. My (server-side) validator tries to update the third party web service with the given field value. If the web service returns true, then the validator also returns true to allow the editor to save the new value. If the third party web service returns false, then my validator returns the error message it received from the third party; allowing the user to know what happened and allowing the editor to discard the change.
Now there is another price field (let it be price2) which is integrated to another third party by almost the same approach with the first price field.
The thing is, price2 depends on price1. So it actually works this way:
-> User enters a price value to the first price field. (price1)
-> I calculate another value for price2. (Using
preSubmit
, see the first post.)-> User saves the form
-> Server-side validator runs for price1, which sends the data to a 3rd party.
-> Server-side validator runs also for price2, which sends the data to another 3rd party.
-> If everything goes well, editor saves the new values for both price1 and price2.
If either of the values fail to succeed on 3rd parties or anything goes wrong with the submission, editor doesn't save the new value for neither of the fields.
Now the problem with this use case is;
-> One of the fields could actually succeed but if the other one failed, then editor couldn't have saved the new value for the field which succeeded. But rather it discards changes of both fields. For example price1 succeeded but price2 failed. Now the third party has the new value, but editor haven't saved it, as one of validators returned false. (This is of course not a bug, this is how it is designed currently.)
-> Dependent code block runs even if there is no change in the field which it depended on. (price1 in this case.)
What could be the solution? Theoretically;
If
dependent()
regards the validator of price1 and runs only when it succeeds (since it is depending on it), then it runs only if there is a change of value in price1 and operates on price2 only if price1 succeeds.Why I call it "theoretically"? Because the problem with this solution is that it requires
dependent()
to have a server-side equivalent I think there is no other way that it could work in this way on client-side. Otherwise it will require to submit the form twice. (Like submit to see if field1 succeeded and now submit field2 which depended on field1)If prices 1 and 2 are interdependent you should do a complete rollback if one of the fields succeed and the other one doesn't. In that regard it is good that Editor discards all changes. (I wrote a lot of banking software some decades ago. Rollbacks were extremely important when updating various ledgers and one of the updates failed. At that time I had to do this stuff "manually" using indexed and sequential files - no database ...).
By the way, I think this is what it would look like if we solve it server-side:
This way, there is still a risk in the case when platform2 fails to update; in which the editor will discard changes on both fields, showing the error of platform2. Now editor and platform1 3rd party is not synchronous.
As per how editor is designed, something has to change fundamentally if we want to "solve" this. Right now, editor is designed to discard changes unless server-side returns true explicitly. Because if it is other than an explicit "true", editor considers "it is false and what it has in return must be the error message". (Which is perfectly normal by design.) But the way I am telling would require editor to check not only an explicit true but also differentiate "false" and "message" from each other.
Like for example in the case I mentioned, saving the price1 field and displaying the error message for price2 field. This is actually not only about
dependent()
. There could be this case too; the new value passes validation but instead of returning an explicit true, it could return true with an additional message like:"Values are saved but something else happened that you need to consider/check whatever bla bla.. " (Ok)
@rf1234 , absolutely. A rollback is also what I was thinking but forgot to mention that it has other drawbacks like;
1- In my case, the regarding web service requires you to wait at least 60 seconds prior to sending another request. (There is another service which even requires 20 minutes )
2- Rollback could fail too. (I know we can't solve everything on one side, but we need to consider every probability.)
ok, one more time
After debating this with Kevin I came to the conclusion that "dependent" should indeed run even if nothing has changed INITIALLY. Otherwise the dynamic hiding and showing of fields "dependent" on the value of other fields wouldn't work when opening the form. (The issue only arises initially because after opening the form I don't see "dependent" being executed if nothing changes.)
If you don't want the "dependent" code to be executed on opening of the Editor form (before anything can get changed) you can replace it by rather simple jQuery like this for example:
Fair point. Then maybe
dependent()
could have another parameter to watch if there is a change. Or it stays this way and the developer has to check if there is a change, like I exemplified in the first post. But in this case, there is still a more robust way of checking needed because I think the way I did may not be multi rows editing aware.On the other hand, I am still confident with what I proposed about the development of the Editor. Right now, editor is evaluating the result like:
true: Value saved, update the table view.
else: It has failed, discard changes and display whatever the server returned.
What I am saying that it might be something more handy like:
@allan consider this
Hi,
Circling back to this as I've been looking at it for the changes to be made for Editor 2.1. Firstly, the issue with pressing return bypassing the dependent action has been resolved (by blurring the focus on submit if it is in a field's input).
Secondly, regarding the different messages for errors in @pisisler's last post. All but the second will work out of the box with Editor as you can return success, a general error message or individual field error messages (details of the data format for that are available in the manual).
The one thing that isn't built in, is the "success, but with a message" state. For that you could listen for
submitComplete
and check for that state and show the message in a notification box. It can't really be shown in Editor since the form is removed at that point due to the successful submission.Allan