-
Notifications
You must be signed in to change notification settings - Fork 2.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Allow to pass in boolean to noDirtyCheck directive #8638
Allow to pass in boolean to noDirtyCheck directive #8638
Conversation
@nul800sebastiaan @nielslyngsoe I believe this will clean up code a bit and we don't need some duplicated code. It looks like we have something like this for |
However for |
I have submitted another PR to fix the issue with |
@kjac maybe you want to test this? 😎 |
This one is too intricate for me to evaluate, I will need some help from @kjac, @nathanwoulfe or if neither can help then @nielslyngsoe. Any takers? 🤞 |
Sure I'll give it a spin in the morning 👍 |
@@ -50,7 +50,7 @@ | |||
|
|||
function onInit() { | |||
vm.inputId = vm.inputId || "umb-check_" + String.CreateGuid(); | |||
|
|||
vm.disableDirtyCheck = vm.disableDirtyCheck === true; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this necessary? And won't it break backwards compat with people using a truthly value that's not strictly true
?
@@ -49,7 +49,7 @@ | |||
|
|||
function onInit() { | |||
vm.inputId = vm.inputId || "umb-radio_" + String.CreateGuid(); | |||
|
|||
vm.disableDirtyCheck = vm.disableDirtyCheck === true; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same as above: Is this necessary? And won't it break backwards compat with people using a truthly value that's not strictly true
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not sure if we need to support both true/false
and 'true'
/'false'
as string values. Here is just do the comparison in the controller so the view is a bit cleaner :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
While certainly cleaner it's also more stringent. My point is that the directive (presumably) supports truthly values today, so it should keep on doing that to preserve compatibility with current usages in 3rd party extensions etc.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We can add more checks here to make it work with other truthly values. E.g.
vm.disableDirtyCheck = vm.disableDirtyCheck === true || vm.disableDirtyCheck === 'true' || vm.disableDirtyCheck === 1;
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I noticed we have this isBool
function in color picker:
https://github.com/umbraco/Umbraco-CMS/blob/v8/contrib/src/Umbraco.Web.UI.Client/src/views/propertyeditors/colorpicker/colorpicker.controller.js#L142-L145
Maybe we should have a global function somewhere to check for truthly values?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Come to think of it we already do - there's an Object.toBoolean(value)
method (defined in Extensions.js).
Object.defineProperty(ctrl, '$pristine', alwaysFalse); | ||
Object.defineProperty(ctrl, '$dirty', alwaysFalse); | ||
// If no attribute value is "false", then skip and use default behaviour. | ||
var dirtyCheck = scope.$eval(attrs.noDirtyCheck) === false; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There must be a native JS function to evaluate a boolean instead of depending on AngularJS to do it for us?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, probably. However I have noticed the $eval
function is used several other places to parse attribute values.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
With the above changes in mind, shouldn't this be var dirtyCheck = Object.toBoolean(attrs.noDirtyCheck) === false;
?
|
||
ctrl.$setDirty = Utilities.noop; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
While I'm sure this works, I'm a tad worried it's too good to be true. The quite intricate solution with the alwaysFalse
binding to $pristine
and $dirty
must be there for a reason... this is just a hunch, but I'm afraid your solution over simplifies things. Wouldn't it be prudent to keep the old solution here, just after the conditional dirty check handling?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not sure if there is a specific reason it change $pristine
. In other alternatives of no-dirty-check
directives I have seen in only change $dirty
. Regarding the "Unsaved changes" dialog it only rely on $dirty
property as far as I know.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yep I agree with you. As I tried to explain, it should work fine, but the current solution seems quite explicitly done as-is. There can be two reasons for this: Either the current solution is over complicated and implemented as such due to lack of knowledge/understanding, or else the current solution covers edge cases we can't right now. My point is it can't hurt to retain the current solution from a better-safe-than-sorry standpoint?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, not sure if $pristine
has any effect on the "Unsaved changes" dialog though. The reason we have the no-dirty-check
directive is to prevent the "Unsaved changes" dialog to show in certain circumstances.
It seems it only rely on $dirty
before opening the overlay here:
Umbraco-CMS/src/Umbraco.Web.UI.Client/src/common/directives/validation/valformmanager.directive.js
Lines 175 to 177 in 0140d90
if (!formCtrl.$dirty && infiniteEditors.length === 0 || isSavingNewItem && infiniteEditors.length === 0) { | |
return; | |
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@bjarnef I see where you're going with this. Code cleanup is always nice 👍 I have left a bunch of comments for you to have a look at.
@kjac it should now check for truthly value 👍 |
Thanks @bjarnef . I left another remark about the usage of Also would you please revert the dirty handling to the previous solution? If you feel very strongly for changing it, you can do so in a new PR, but please be absolutely certain that you know exactly why the previous solution is written in such a cumbersome way before attempting to change it. |
@kjac I have reverted the dirty handling for now and changes to Regarding the "Unsaved changes" I don't think the Umbraco-CMS/src/Umbraco.Web.UI.Client/src/common/directives/validation/valformmanager.directive.js Lines 175 to 177 in 0140d90
To me it seems it was just taken from one of the first results on Google, but no comment left, why it need to change |
@bjarnef finally got around to giving this a test run. It seems your solution didn't take into account the default (undefined) values when the directives were applied without true/false. I have pushed a fix in 0a5b442 - have a look. Here's a test dashboard you can use with all combinations of dirty checking: <div ng-controller="MyDashboardController as vm">
<div>
<input type="text" name="text1" placeholder="no-dirty-check" ng-model="text1" no-dirty-check />
</div>
<div>
<input type="text" name="text2" placeholder="no-dirty-check="false"" ng-model="text2" no-dirty-check="false" />
</div>
<div>
<input type="text" name="text3" placeholder="no-dirty-check="true"" ng-model="text3" no-dirty-check="true" />
</div>
<div>
<umb-checkbox model="check0" name="check0" disable-dirty-check>disable-dirty-check</umb-checkbox>
</div>
<div>
<umb-checkbox model="check1" name="check1" disable-dirty-check="false">disable-dirty-check="false"</umb-checkbox>
</div>
<div>
<umb-checkbox model="check2" name="check2" disable-dirty-check="true">disable-dirty-check="true"</umb-checkbox>
</div>
<div>
<umb-radiobutton model="radio0" name="radio0" disable-dirty-check>disable-dirty-check</umb-radiobutton>
</div>
<div>
<umb-radiobutton model="radio1" name="radio1" disable-dirty-check="false">disable-dirty-check="false"</umb-radiobutton>
</div>
<div>
<umb-radiobutton model="radio2" name="radio2" disable-dirty-check="true">disable-dirty-check="true"</umb-radiobutton>
</div>
</div> |
@kjac strange Thus returning |
@bjarnef exactly; but "no value" is supposed to mean |
@kjac okay, then we might need a |
@bjarnef that was my thought too, and surely it can't hurt to add them, but try as I might I could only manage to pass |
@nathanwoulfe I wonder if you may have an idea why I am starting to see this console error? I wonder if something has changed in Angular v1.8.0?
It would be an issue if |
Not sure, but it could be due to using attrs rather than scope to access the value - if the value is bound in the view, and has changes, perhaps Angular is aware that it has changed, but can't propagate the change to the directive since it's not a scoped input. That's a guess, and a big one... |
@nathanwoulfe it doesn't seem to be related to the use of If I comment out the line where |
Hello @bjarnef , Thanks for all the investigations! I went and tested again and I think there were some remaining issues if we wanted values After scratching my head for a while, I kind of "started from scratch" for the construction of the conditions. From what I understood, the behaviour we want is something like "skip the no-dirty-check logic only if the attribute is not provided (in which case you don't get into the logic in fact :-)) or if its value is explicitly set to false, go for it in all other cases". So I rewrote the conditions in the noDirtyCheck directive to match exactly that. The Object.ToBoolean does not fit for this since it actually does the opposite: anything is false except if it's explicitly set to true. I also rewrote the conditions in the radio/checkbox controllers so that they provide the correct true/false values to the no-dirty-check attribute. I made tests with all the possibilities you mentioned, and it behaves as expected: only when we do not set the attribute or when we explicitly set no-dirty-check="false" (or 0), we get the "Unsaved Changed" warning. Let me know what you think 😁 I'll try to have a look tonight for the console errors Cheers! |
@mikecp yeah the Regarding So the value need to be "0" (int or string) or "false" (bool or string) to "disable" this (like if this attribute isn't added which make the form field dirty and trigger the "Unsaved changes" dialog. Regarding |
Hi @bjarnef, Thanks for your feedback! |
I think it comes down to that With |
Hey @bjarnef , I start to mixup what was said in the different messages😃 . So if I try to summarize, what we want is:
Regarding disable-dirty-check, the more I look at it, the more it looks like just a pass-through to the "no-dirty-check" attribute of the form control beneath it. Son I am starting to think that we might just pass its value as-is to the no-dirty-check directive, and let that one interpret it following the rules above... Since no-dirty-check now handles all possible values sent, is that not the easiest way to keep the logic homogeneous? Cheers! |
@mikecp correct about the Yeah, er han probably just pass the value through. Not that important as it from start was supposed to use true/false values and is a property, while the other is a directive. It might could to check what happens with no Could you give this a last spin, then I think we are pretty close and definitely cleanup the views. |
@mikecp did you had a change to look at this again? would be great to close this and make the code a bit cleaner 😎 |
Hey @bjarnef , |
@mikecp did you found some time to look at this again? Let me know if you need further info or I can help with anything 😎👍 |
@mikecp anything I can help with to get this closed/merged. I would really like to cleanup some of the redundant code 🙈🤓 |
Hi @bjarnef , |
Changes have been integrated + adapted further
Hi @bjarnef , I finally found the time to make the last checks on this PR 🎉😂 Testing on undefined, null and empty values for So I can finally merge this, with all my apologies for this long delay 😅 Thanks again for this PR and for your patience 👍 |
Hi @mikecp Thanks for testing it again and reviewing the code. Great to have this redundant code cleaned up and will be useful in future development easy to enable/disable the dirty check. 👍 |
Prerequisites
Description
At the moment we have some duplicated logic to be able to set
no-dirty-check
directive on e.g.<umb-checkbox>
and<umb-radiobutton>
.I would however like just to pass in a boolean value whether to set this or not.
For example:
no-dirty-check
without attribute value set$dirty
to false.no-dirty-check="true"
with attribute valuetrue
works as before mentioned.no-dirty-check="false"
with attribute valuetrue
works as default behaviour.The directive was originally created based on this https://stackoverflow.com/a/27430980 but note sure why we need the local variable with getter and setter. Furthermore why it change
$pristine
. It seems this was changed in #2476I found some different variants setting
$dirty
tofalse
orangular.noop
:https://stackoverflow.com/a/29225603
Test notes
no-dirty-check
,no-dirty-check="true"
andno-dirty-check="true"
on<input>
field works as expected. Also check with<umb-checkbox>
and<umb-radiobutton>
usingdisable-dirty-check
property withtrue/false
value.MyDashboard.zip