I'm facing a problem where i cannot bind :invalid css selector with my input since i have custom validation. invalid is only active with basic validator example: input type="email" so the invalid will work with example# or example#example.exmaple while my function only validates the last one (example#example.example).
Project Link
HTML FILE
<input class="custom-input" type="email" [(ngModel)]='Email' name="email" placeholder="Email" formControlName="emailTxt">
<div class="err>
this is an error
</div>
TypeScript File
this.signUpForm = this._fb.group({
emailTxt: [null, Validators.compose([
Validators.required
])]
}, {
validators: [
EmailValidation('emailTxt'),
]
});
Form Validation Function
export function EmailValidation(controlName: string) {
return (formGroup: FormGroup) => {
const control = formGroup.controls[controlName];
if (control.errors && !control.errors.invalidEmail) {
return;
}
if (control.value.trim().match(/^([a-zA-Z0-9_\-\.]+)#((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.)|(([a-zA-Z0-9\-]+\.)+))([a-zA-Z]{1,5}|[0-9]{1,3})(\]?)$/) == null) {
control.setErrors({ invalidEmail: true });
}
else {
control.setErrors(null);
}
}
}
CSS File
.custom-input:invalid{
& ~ .err {
max-height: 200px;
padding: 0 18px 10px 20px;
color: red;
}
}
i expect the invalid selector should to be triggered with every control.setErrors() function
Add below CSS code in your project, that's definitely works
input.ng-dirty.ng-invalid {
border: 1px solid red;
}
This will work Definitely ☺ add to ur css file
input.ng-invalid.ng-touched, select.ng-invalid.ng-touched {
border: 1px solid red !important;
}
Related
I am using Material-UI v5 for my project. I need to style my scrollbars using the following css
body::-webkit-scrollbar {
width: 12px;
}
body::-webkit-scrollbar-track {
background: blue;
}
body::-webkit-scrollbar-thumb {
background-color: red;
border: 3px solid black;
border-radius: 10px;
}
I tried using makeStyles as following:
const useStyles = makeStyles((theme: Theme) => ({
root: {
background: theme.palette.primary.main,
'html': {
scrollbarWidth: 'thin',
scrollbarColor: theme.palette.accent.main
},
'body::-webkit-scrollbar': {
width: '12px'
},
'body::-webkit-scrollbar-track' : {
background: theme.palette.primary.main,
}
},
}));
But when I inspect the actual source css was coming as 'body::-webkit-scrollbar' : Object[object].
I am stuck on how to add global css like this in material-ui and what is the best way to do this.
Also please let me know incase I am doing anything wrong here. Thanks in advance.
How to validate emails?
Would you please show an example with an error message?
Documentation does not give enough details.
It seems there is nothing like v-if="!$v.user.email.email"
Following code does not work either
validations: {
user: {
email: {
required,
email: email(),
},
}
}
Actualy, I was wrong and there was something like v-if="!$v.user.email.email"
You do not need any details for email validator.
All you need is
email: {
email,
},
If you had any Vetur errors just uninstall Vetur and reinstall it.
Vue.use(window.vuelidate.default)
const { email } = window.validators
new Vue({
el: "#app",
data: {
user: {
email: ""
}
},
validations: {
user:{
email: {
email
}
}
},
methods: {
status(validation) {
return {
error: validation.$error,
dirty: validation.$dirty
}
}
}
})
input {
border: 1px solid silver;
border-radius: 4px;
background: white;
padding: 5px 10px;
}
.dirty {
border-color: #5A5;
background: #EFE;
}
.error {
border-color: red;
background: #FDD;
}
<script src="https://cdn.jsdelivr.net/combine/npm/vuelidate#0.7.5/dist/validators.min.js,npm/vuelidate#0.7.5/dist/vuelidate.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<input v-model="$v.user.email.$model" :class="status($v.user.email)">
<div class="error" v-if="!$v.user.email.email">this must be an email</div>
<pre>{{ $v }}</pre>
</div>
Answer https://stackoverflow.com/a/61359412/11993949 shows off how to use on blur functionality too
you can use this regex validation pattern to validate your email.
[a-zA-Z0-9]+#[a-z]+\.[a-z]{2,3}
If you are getting as json format you can try this
[a-zA-Z0-9]+#[a-z]+\\.[a-z]{2,}
I need to show a tooltip which is a Html list on hover.
I can show the date highlighted and a simple message but the list wont show at all. It has to do with the bootstrap. If I remove bootstrap then it shows but I need bootstrap in the app. Is there any way to show a list in a tooltip on hover with bootstrap?
Here is the code
export class DatepickerDateClassExample {
list: string =
"Date - (3)<br/>" +
"Names - (4)<br/>" +
"Addresses - (25)<br>" +
"Values - (30)";
constructor(private renderer: Renderer2) {}
dates = [
{ date: "2020-04-20", text: this.list }
];
dateClass = (d: Date) => {
const dateSearch = this.dateToString(d);
return this.dates.find(f => f.date == dateSearch)
? "example-custom-date-class"
: undefined;
};
displayMonth() {
let elements = document.querySelectorAll(".endDate");
let x = elements[0].querySelectorAll(".mat-calendar-body-cell");
x.forEach(y => {
const dateSearch = this.dateToString(
new Date(y.getAttribute("aria-label"))
);
const data = this.dates.find(f => f.date == dateSearch);
if (data) y.setAttribute("aria-label", data.text);
});
}
streamOpened(event) {
setTimeout(() => {
let buttons = document.querySelectorAll("mat-calendar .mat-icon-button");
buttons.forEach(btn =>
this.renderer.listen(btn, "click", () => {
setTimeout(() => {
//debugger
this.displayMonth();
});
})
);
this.displayMonth();
});
}
dateToString(date: any) {
return (
date.getFullYear() +
"-" +
("0" + (date.getMonth() + 1)).slice(-2) +
"-" +
("0" + date.getDate()).slice(-2)
);
}
Css:
::ng-deep .example-custom-date-class {
background: orange;
border-radius: 100%;
}
.tooltip
{
display: none;
position: absolute;
text-align: center;
margin-top: 30px;
width: 155px;
padding: 10px;
z-index: 2000;
box-shadow: 0px 0px 4px #222;
border-radius: 10px;
background-image: -webkit-gradient(linear,left top,left bottom,color-stop(0, #eeeeee),color-stop(1, #cccccc));
background-image: -webkit-linear-gradient(top, #eeeeee, #cccccc);
color: gray;
}
.tooltip:before {
content: '';
display: block;
position: absolute;
left: 10px;
top: -20px;
width: 0;
height: 0;
border: 9px solid transparent;
border-bottom-color: #cccccc;
}
Html:
<mat-form-field class="example-full-width" >
<input matInput [matDatepicker]="picker" placeholder="Choose a date">
<mat-datepicker-toggle matSuffix [for]="picker"></mat-datepicker-toggle>
<mat-datepicker (opened)="streamOpened($event)" [dateClass]="dateClass" #picker panelClass="endDate" ></mat-datepicker>
</mat-form-field>
<div #toolTip class="tooltip" (mouseover)="onTool=true"
(mouseout)="onTool=false"
[style.display]="show || onTool?'inline-block':'none'" [innerHTML]="toolTipMessage">
</div>
Here is the stackblitz
I'm afraid that you can not use a simple css, because content only admit \A to make a break line but it's not possible using attr -it's possible indicate que \A as string in the content- (and don't allow .html)
Well, we can take another aproach that is use a div that make as tooltip and use renderer to listen mouseout and mouseover
If our div is like
<div #toolTip class="tooltip"
(mouseover)="onTool=true"
(mouseout)="onTool=false"
[style.display]="show || onTool?'inline-block':'none'"
[innerHTML]="toolTipMessage">
</div>
And has two variables and get the div using ViewChild
#ViewChild('toolTip') tool:ElementRef
show:boolean=false;
onTool:boolean=false;
We can change our function displayMonth to add the mouseover and mouse out
displayMonth() {
let elements = document.querySelectorAll(".endDate");
let x = elements[0].querySelectorAll(".mat-calendar-body-cell");
x.forEach(y => {
const dateSearch = this.dateToString(
new Date(y.getAttribute("aria-label"))
);
const data = this.dates.find(f => f.date == dateSearch);
if (data) {
this.renderer.listen(y, "mouseover", () => this.showTool(y, data.text));
this.renderer.listen(y, "mouseout", () => this.hideTool());
}
});
}
showTool(y, data) {
this.show = true;
this.toolTipMessage = data;
this.renderer.setStyle(
this.tool.nativeElement,
"top",
y.getBoundingClientRect().y+ "px"
);
this.renderer.setStyle(
this.tool.nativeElement,
"left",
y.getBoundingClientRect().x + "px"
);
}
hideTool() {
this.show = false;
}
See the stackblitz
You just need to set the tooltip's opacity to 1. Bootstrap sets tooltip's classes opacity to 0 by default.
.tooltip
{
/*.... */
opacity: 1;
}
You could also just change your class name and not use tooltip.
Modified stackblitz
Explanation
If you use native bootstrap js, you normally need to call the .tooltip('show') method on the element for which the tooltip should appear. This will in turn change the opacity of the tooltip element.
Here, it looks like you are just using the css part of bootstrap, not the js lib, so you need to change the opacity yourself.
Note: using bootstrap's js requires jquery, which is not recommended in angular projects. There are some like libraries out there which provide bootstrap components for angular without requiring jquery, like ngx-bootstrap
Edit
Just for info, if you really wanted to use jquery and bootstrap for your tooltip, have a look at this stackblitz example.
Basically, you just call tooltip on the calendar dates and pass the text to display. Bootstrap will handle hiding/showing and positionning of the tooltip.
$(y).tooltip({'title': data.text, html: true});
I have valid and invalid attributes for my input areas but for my retype password i am using js to match the password, the input stays red, i just want to target that input/textarea and give my own colors, i have tried this code but it changes all the input areas and not the retype input.
input:focus:invalid,
textarea:focus:invalid[required][name="retypepassword"] {
border:2px solid green;
box-shadow:0 0 4px #F5192F;
color:blue;
}
This my actual css:
textarea:focus, input:focus {
outline: 0;
}
input:focus:invalid,
textarea:focus:invalid {
border:2px solid #F5192F;
box-shadow:0 0 4px #F5192F;
color:red;
}
input:focus:valid,
textarea:focus:valid {
border: 2px solid #09c;
box-shadow: 0 0 4px #09c;
}
Basically I'm trying to target the retype password input and textarea ?
i have this line of code which is probably overriding it?
input[required]:invalid {
background: #efdee0 url(../images/invalid.png) no-repeat center
right;
}
input[required]:valid {
background: hsla(235, 100%, 96%, 1) url(../images/valid.png)
no-repeat center right;
}
The js is causing the input not to validate and change to valid, therefore changed to the following code which worked:
$().ready(function(){
$("#registration").validate({
rules: {
pswd: {
required: true
},
retypepassword: {
required: true,
equalTo: "#pswd"
}
},
messages: {
pswd: "Please enter password",
retypepassword: "Please enter valid confirm password"
},
submitHandler: function() { $('#registration').submit(); }
});
});
Initially i wanted to target the retype input because the validation was not working so i can change it to a neutral color and not add validation on the retype.
It's impossible to use placeholder on date fields but I really need it.
I want two date inputs with texts "From" and "To" on each one as placeholders.
I'm using the following CSS only trick:
input[type="date"]:before {
content: attr(placeholder) !important;
color: #aaa;
margin-right: 0.5em;
}
input[type="date"]:focus:before,
input[type="date"]:valid:before {
content: "";
}
<input type="date" placeholder="Choose a Date" />
use this input attribute events
onfocus="(this.type='date')" onblur="(this.type='text')"
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous">
<div class="container mt-3">
<label for="date">Date : </label>
<input placeholder="Your Date" class="form-control" type="text" onfocus="(this.type='date')" onblur="(this.type='text')" id="date">
</div>
You can use CSS's before pseudo.
.dateclass {
width: 100%;
}
.dateclass.placeholderclass::before {
width: 100%;
content: attr(placeholder);
}
.dateclass.placeholderclass:hover::before {
width: 0%;
content: "";
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script>
<input
type="date"
placeholder="Please specify a date"
onClick="$(this).removeClass('placeholderclass')"
class="dateclass placeholderclass">
FIDDLE
You can do something like this:
<input onfocus="(this.type='date')" class="js-form-control" placeholder="Enter Date">
The HTML5 date input field actually does not support the attribute for placeholder. It will always be ignored by the browser, at least as per the current spec.
As noted here
I'm using this css method in order to simulate placeholder on the input date.
The only thing that need js is to setAttribute of the value, if using React, it works out of the box.
input[type="date"] {
position: relative;
}
input[type="date"]:before {
content: attr(placeholder);
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: #fff;
color: rgba(0, 0, 0, 0.65);
pointer-events: none;
line-height: 1.5;
padding: 0 0.5rem;
}
input[type="date"]:focus:before,
input[type="date"]:not([value=""]):before
{
display: none;
}
<input type="date" placeholder="Choose date" value="" onChange="this.setAttribute('value', this.value)" />
The input[type="date"] DOMElement only takes the following value: YYYY-MM-DD, any other format or text with be skipped.
var element = document.querySelectorAll('[placeholder]');
for (var i in element) {
if (element[i].nodeType == 1 && element[i].nodeName == "INPUT") {
element[i].value = element[i].getAttribute('placeholder');
element[i].style.color = "#777";
element[i].onfocus = function(event) {
if (this.value == this.getAttribute('placeholder')) {
this.value = "";
this.style.color = "#000"
};
};
element[i].onblur = function(event) {
if (this.value == "") {
this.value = this.getAttribute('placeholder');
this.style.color = "#777";
}
};
}
}
<input type="text" placeholder="bingo" />
<input type="date" placeholder="2013-01-25" />
In this exact case, with 2 input elements, Pure JavaScript is ~40% ± 10% faster. With 32 input elements, the difference remains the same (~43% ± 10% faster for Pure JS).
Got the most easiest hack for this problem-use this syntax in your HTML-input-tag
<input type="text" id="my_element_id" placeholder="select a date" name="my_element_name" onfocus="(this.type='date')" />
</div>
Try this:
Add a placeholder attribute to your field with the value you want, then add this jQuery:
$('[placeholder]').each(function(){
$(this).val($(this).attr('placeholder'));
}).focus(function(){
if ($(this).val() == $(this).attr('placeholder')) { $(this).val(''); }
}).blur(function(){
if ($(this).val() == '') { $(this).val($(this).attr('placeholder')); }
});
I've not tested it for fields that can't take placeholders but you shouldn't need to change anything in the code at all.
On another note, this code is also a great solution for browsers that don't support the placeholder attribute.
As mentionned here, I've made it work with some ":before" pseudo-class and a small bit of javascript.
Here is the idea :
#myInput:before{ content:"Date of birth"; width:100%; color:#AAA; }
#myInput:focus:before,
#myInput.not_empty:before{ content:none }
Then in javascript, add the "not_empty" class depending on the value in the onChange and onKeyUp events.
You can even add all of this dynamically on every date fields. Check my answer on the other thread for the code.
It's not perfect but it's working well in Chrome and iOS7 webviews. Maybe it could help you.
As i mentioned here
initially set the field type to text.
on focus change it to type date
just use it :
var elementDate = $('input[type="date"]');
$.each(elementDate, (key, value) => {
if (!$(value).val()) {
$(value).css("color", "#777");
}
$(value).on("focus", function (event) {
$(this).css("color", "#000");
});
$(value).on("blur", function (event) {
if (!$(this).val()) {
$(this).css("color", "#777");
}
});
});
Ok, so this is what I have done:
$(document).on('change','#birthday',function(){
if($('#birthday').val()!==''){
$('#birthday').addClass('hasValue');
}else{
$('#birthday').removeClass('hasValue');
}
})
This is to remove the placeholder when a value is given.
input[type="date"]:before {
content: attr(placeholder) !important;
color: #5C5C5C;
margin-right: 0.5em;
}
input[type="date"]:focus:before,
input[type="date"].hasValue:before {
content: "" !important;
margin-right: 0;
}
On focus or if .hasValue, remove the placeholder and its margin.
Using a jQuery (sure you can achieve this with Vanilla. This make sure the date format still the same.
$(function() {
$('.sdate').on('focus', function() {
$(this).attr('type', 'date');
});
$('.sdate').on('blur', function() {
if(!$(this).val()) { // important
$(this).attr('type', 'text');
}
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.0.0/jquery.min.js"></script>
<input type="text" class="sdate" placeholder="From">
CSS
input[type="date"] {position: relative;}
input[type="date"]:before {
position: absolute;left: 0px;top: 0px;
content: "Enter DOB";
color: #999;
width: 100%;line-height: 32px;
}
input[type="date"]:valid:before {display: none;}
<input type="date" required />