-
Notifications
You must be signed in to change notification settings - Fork 3.4k
feat(md-chips): added validation for ng-required #11125
feat(md-chips): added validation for ng-required #11125
Conversation
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.
Please add "Fixes #11124" on the last line of your commit (as mentioned in the commit message guidelines).
</div> | ||
</form> | ||
</md-content> | ||
</div> |
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.
Blank line at end of file please.
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.
This is a good start! However, I think that there are a few more finishing touches to put on this feature to make it align with md-input.
this.selectedFruit = []; | ||
this.selectedVegetables = []; | ||
} | ||
})(); |
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.
Blank line at end of file please.
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 fixed @Splaktar ? Because in the code it seems like, but just the one comment of you got hidden, this here not.
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, looks good now.
</md-chips> | ||
<div ng-messages="fruitForm.fruit.$error"> | ||
<div ng-message="required">At least one fruit is required</div> | ||
</div> |
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.
These don't show up red because the chips-theme.scss
is lacking styles for md-invalid
. Can you please review the input-theme.scss
and implement something similar for chips as part of this PR?
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.
input.scss
also uses a md-input-message-animation
class to animate the message in and to set a smaller line height and font size (among other things). Can we please add those styles to chips.scss
so that they will be similar when used in a form together?
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.
The error message is showing up even when the input is pristine and not dirty. For input, this isn't the case. Can you please look into this?
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.
Ok, I found out what md-input-container is doing: It adds a special animation-class md-input-messages-animation
(https://github.com/angular/material/blob/v1.1.7/src/components/input/input.js#L840) and does some stuff with it. I see two ways here. A: make the demos with md-chips inside md-input-container and assure that this have the same look&feel. B: Add a chips-special-class and add styles there.
But B is not really following the ways it is made atm. ng-messages is just styled inside certain containers. So just A is left, but are chips belonging to md-input-container? - Is there any rule which forbids it?
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, I can see how we wouldn't want to style ng-messages
that aren't contained in an AngularJS Material component. I've asked @devversion for some input and created a CodePen to demonstrate how ng-messages
are styled with chips today (with md-max-chips
) for reference since there is no example in the demos.
293af81
to
7f4a978
Compare
@Splaktar you labeled this PR and the related issue with "bug". Is it a bug or feature in your opinion? - because then I should adjust the commit-message-prefix. |
Yeah, I think you are right. I'll updated this to |
I think just implementing the logic for supporting the For now, we could just have some custom CSS in the demo and maybe show a small caption under the chips demo that explains that there is no default CSS for error messages yet. Placing chips inside of the The As you see, this turns out to be a whole new issue, so I'd say that this should be handled in a follow-up. |
@devversion thank you very much. That makes a lot of sense. @IMM0rtalis can you please look at #11125 (comment) and then add the styles to the demo along with a note about developers needing to style the |
a91fc9a
to
c60f055
Compare
@Splaktar I added the note and example-styles and conditional ng-show of error-messages in the demo. |
@IMM0rtalis is there a way to use this branch in a project ? I tried without success : "devDependencies": {
"angular-material-source": "git+https://github.com/IMM0rtalis/material.git#c60f055728e1102afa7bb5e9d6e18df021000941"
} I was using "devDependencies": {
"angular-material": "1.1.6"
} |
@salimane not sure, but until the next version with this included is published you could try a hacky way (we had to do it for now) /**
* Fix MdChipsController
* - fixes problem with not validating required-field (fix in v1.1.8)
*
* @see https://github.com/angular/material/pull/11125
*/
(function() {
function updateMdChipsController(MdChipsCtrl) {
/**
* Updates the validity properties for the ngModel.
*/
MdChipsCtrl.prototype.validateModel = function() {
this.ngModelCtrl.$setValidity('md-max-chips', !this.hasMaxChipsReached());
this.ngModelCtrl.$validate(); // rerun any registered validators
};
/**
* Configures the required interactions with the ngModel Controller.
* Specifically, set {@code this.items} to the {@code NgModelCtrl#$viewVale}.
* @param ngModelCtrl
*/
MdChipsCtrl.prototype.configureNgModel = function(ngModelCtrl) {
this.ngModelCtrl = ngModelCtrl;
var self = this;
// in chips the meaning of $isEmpty changes
ngModelCtrl.$isEmpty = function(value) {
return !value || value.length === 0;
};
ngModelCtrl.$render = function() {
// model is updated. do something.
self.items = self.ngModelCtrl.$viewValue;
};
};
}
var invokes = angular.module('material.components.chips')._invokeQueue,
i;
for(i=0; i < invokes.length; ++i) {
if(invokes[i][0] === "$controllerProvider" && invokes[i][2][0] === "MdChipsCtrl") {
updateMdChipsController(invokes[i][2][1]);
}
}
})(); |
thanks @IMM0rtalis . what is the connection between the current repo and this one https://github.com/angular/bower-material . Thanks |
@salimane bower-material is the repo where the releases live. This is what gets installed by bower or NPM. Everytime we merge something into master (including making a release), a new, installable build is generated in bower-material and available to Bower and NPM. |
@Splaktar thanks for reply. Do you think there is way to have a branch in https://github.com/angular/bower-material that will use the changes in the current pull-request ? Thanks |
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.
This looks good. I just had a couple questions.
@@ -170,18 +177,40 @@ MdChipsCtrl.prototype.init = function() { | |||
var ctrl = this; | |||
|
|||
// Set the wrapper ID | |||
ctrl.wrapperId = '_md-chips-wrapper-' + ctrl.$mdUtil.nextUid(); | |||
this.wrapperId = '_md-chips-wrapper-' + this.$mdUtil.nextUid(); |
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.
What's the benefit of the changes on this line?
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.
Actually I do not see a point in using a helper-var instead of this
if this
is usable in a place. In my opinion it reduces the readability of code. And if the helper-var for encapsulated inner functions is called ctrl
, self
or that
is in my opinion too much a matter of taste (otherwise I would have replaced ctrl
with more widely used helpers in this repository)
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.
Ah OK. 👍
); | ||
|
||
this.deRegister.push( | ||
this.$scope.$watch('$mdChipsCtrl.items', function() { |
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.
The comment here is the same as above. What's the reason that this new $watch
is needed?
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.
You are just pointing out the replacement of ctrl
with this
, right? Then see comment above^^
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.
Nope, I'm asking about the two comments "Make sure our input and wrapper have the correct ARIA attributes" and the existing $watchCollection
versus the new $watch
.
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 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.
Wait... this is duplicated. Fix it asap
var $destroyFn; | ||
while (($destroyFn = this.deRegister.pop())) { | ||
$destroyFn.call(this); | ||
} |
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.
Why is this made so complicated? What about just this.unregisterFunctions.forEach(fn => fn());
?
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.
Because it is ES6, right? Is this repo require es6 ?
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.
ES6 is fine in the build scripts and docs site, but not in the production library code (i.e. anything in src/
).
However, you can still use Array.foreach as it's ES5, just not the arrow functions.
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, using the ES5
forEach
method should be still a benefit.
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.
If the comparisson-tests are not completely setup wrong I think the while pop is in all cases faster. Have I made a mistake or is there an other reason for using forEach over while-pop?
https://jsperf.com/foreach-vs-while-pop
http://jsben.ch/IGesk
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.
Other than those two nits. LGTM
this.deRegister.push( | ||
this.$scope.$watch( | ||
function() { | ||
return ngModelCtrl.$touched; |
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.
You can combine this single watch into two. e.g.
this.$scope.$watch(() => {
return { touched: inputNgModelCtrl.$touched, dirty: inputNgModelCtrl.$dirty };
}, XXXX);
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.
But dont I need $watchCollection for this? And then separate afterwards anyway?
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.
Don't think a $watchCollection
will work here, because it requires us to watch properties on the $scope
. Using $watch
and just having a different watch condition should work.
https://stackoverflow.com/questions/17550947/how-to-watch-multiple-variables
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.
If I do as suggested I run in an endless digest-cycle with karma. What speaks against having two simple watcher?
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.
Let's leave it as is, thanks for giving it a try.
@tinayuangao or @jelbourn or @andrewseguin or @josephperrott or @mmalerba |
@IMM0rtalis there is no need to mention all of the caretakers. The issue can't be merged until it passes internal presubmit testing. @tinayuangao started the presubmits on this on 2/27, but I haven't received the results from that yet. I've pinged her for that information. Thank you for the reminder. |
Presubmits failed. The failures are being investigated. I'll provide more details when they are available. |
Ahh ok. I thought they are the ones who should merge it (https://github.com/angular/material/blob/master/docs/guides/COMMIT_LEVELS.md) and since there was no update... But yeah, they are often not passing I have the feeling :D |
Yep, they will merge it when presubmits get sorted out and any internal failures are fixed (by them). They rotate shifts each week, so mentioning them all isn't ideal. I know who is on shift each week and I work with them to get the merges run through presubmit and merged. This process starts after I apply the We recently updated many of the tag descriptions (new GitHub feature) to help make this process a bit more clear. I'll try to document a bit more of the process in the commit levels guide when I have some time. |
Passes presubmit |
…)" This reverts commit ba0e9fe.
This appears to have caused a regression related to adding chips onBlur. We're planning to revert it in #11215 and do more investigation/testing. |
* Revert "feat(chips): trigger ng-change on chip addition/removal (angular#11166)" This reverts commit 19da42d. * Revert "feat(md-chips): added validation for ng-required (angular#11125)" This reverts commit ba0e9fe.
* feat(md-chips): added validation for ng-required (angular#11125) Fixes angular#11124 (cherry picked from commit ba0e9fe) * fix(chips): allow adding chips on blur when the model is empty Fixes angular#11217. Relates to angular#11125.
PR Checklist
Please check that your PR fulfills the following requirements:
PR Type
What kind of change does this PR introduce?
What is the current behavior?
ng-required not working with md-chips
Issue Number: #11124
What is the new behavior?
ng-required works with md-chips
Does this PR introduce a breaking change?
Other information
Pull-Request is mainly a follow-up from #8034. I had the same idea in how to add this but found this not followed/merged pull-request by @Emeegeemee .
So nearly everything of the code got reviewed once by @devversion & @crisbeto . I just changed the naming a bit.