angular ngModel style - html

Is it possible to style the value in the attribute ngModel of an input tag?
Example:
<input class="input" type="text" [(ngModel)] = "myService.text">
Let's say the value of text is '28 packages', can I put 28 in bold?

So if i understand correctly you want to have it bold whenever the value is 28 ?
yes its possible you can use a ng-class with a ternary expression like this
.bold{
font-weight:600;
}
<input type="text" ng-class="myService.text == '28 ? 'bold' : '''" class="input" ng-model="myService.text" />

This is not angular-related rather a CSS related question.
You cannot style only a part of an input in HTML/CSS so you won't be able to do it in angular.
Instead, you can use an input that is hidden behind a div. The idea is that when the user clicks the div, you actually focus the input. When the user types text, you capture the content of the input and fill the div with it, eventually adding <span class"highlight"> around the number of packages.
I prepared you a stackblitz in pure CSS/JS. You can adapt it in angular if you want.
Relevant pieces of code :
HTML :
<span id="hiddenSpan">This is the hidden div. Click it and start typing</span>
<div>
<label for="in">The real input</label>
<input id="in" type="text">
</div>
JS :
const input = document.getElementById('in')
const hiddenSpan = document.getElementById('hiddenSpan')
function onInputChanged() {
let text = input.value
const regex = new RegExp('(\\d+) packages')
let result = regex.exec(text)
if(result) {
hiddenSpan.innerHTML = '<span class="highlight">'+result[1]+'</span> packages'
} else {
hiddenSpan.innerHTML = text
}
}
// Capture keystrokes.
input.addEventListener('keyup', onInputChanged)
// Focus the input when the user clicks the pink div.
hiddenSpan.addEventListener('click', function() {
input.focus()
})
CSS :
#hiddenSpan {
background-color: pink;
}
.highlight {
font-weight: bold;
background-color: greenyellow;
}
Note : the downside is that the blinking caret is not visible anymore. You can take a look at this resource if you want to simulate one.

It is not possible to style certain parts of a text <input> field in bold. However, you can use a contenteditable div instead of a text <input> field. Inside the contenteditable div you can have other HTML tags like <strong> to style certain parts of the text however you like.
I created an Angular directive called contenteditableModel (check out the StackBlitz demo here) and you can use it to perform 2-way binding on a contenteditable element like this:
<div class="input" contenteditable [(contenteditableModel)]="myService.text"></div>
The directive uses regular expressions to automatically check for numbers in the inputted text, and surrounds them in a <strong> tag to make them bold. For example, if you input "28 packages", the innerHTML of the div will be formatted like this (to make "28" bolded):
<strong>28</strong> packages
This is the code used in the directive to perform the formatting:
var inputElement = this.elementRef.nativeElement;
inputElement.innerHTML = inputElement.textContent.replace(/(\d+)/g, "<strong>$1</strong>");
this.change.emit(inputElement.textContent);
You can change the <strong> tag to something else (e.g. <span style="text-decoration: underline"> if you want the text to be underlined instead of bolded).
When performing the formatting, there is an issue where the user's text cursor position will be unexpectedly reset back to the beginning of the contenteditable div. To fix this, I used 2 functions (getOriginalCaretPosition and restoreCaretPosition) to store the user's original cursor position and then restore the position back after the text formatting is performed. These 2 functions are kind of complex and they're not entirely relevant to the OP's question so I will not go into much detail about them here. You can PM me if you want to learn more about them.

Related

How can I restrict a time input value?

I want to display an input type hour from 08:00 to 20:00. I tried this:
<input type="time" id="timeAppointment" name = "timeAppointment" min="08:00" max="20:00" placeholder="hour" required/>
But when I display it I can still select any time, it does not restrict me as I indicate. What is the problem? If is necessary some code I work with Javascript.
The constraints within the input do not prevent from entering an incorrect value in this case. Here is an overview of what MDN says in their documentation:
By default, does not apply any validation to entered values, other than the user agent's interface generally not allowing you to enter anything other than a time value.
But you can write validations with JavaScript, or visual validations with CSS, like so:
.container{
display:flex;
align-items:center;
gap:1rem;
}
input:invalid+span:after {
content: '✖';
}
input:valid+span:after {
content: '✓';
}
<div class = "container">
<input type="time" id="timeAppointment" name = "timeAppointment" value="08:00" min="08:00" max="20:00" placeholder="hour" required/>
<span class="validity"></span>
</div>
Setting min and max properties in input tags do not inherently prevent you from accepting out of range values as inputs, but it controls the valid property of the tag, which can then be used such as in css to style your page accordingly. Some browsers do make it so that you cannot input out of the specified range, but it is not platform-independent behaviour.
See more here: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input/time#setting_maximum_and_minimum_times
If you want to ensure that only the time between min and max are input, you could programmatically implement that using an onchange listener on your input element as follows:
Make sure to indicate to the user why their input is not changing (because it is not between min and max) using css and text, etc.
const timeInput = document.getElementById("timeAppointment");
timeInput.value = '15:56';
let previousValue = timeInput.value;
timeInput.onchange = () => {
console.log(previousValue)
console.log(timeInput.value)
if (timeInput.value < timeInput.min || timeInput.value > timeInput.max) {
timeInput.value = previousValue;
}
previousValue = timeInput.value;
}
<input type="time" id="timeAppointment" name="timeAppointment" min="08:00" max="20:00" required/>
However, there is a caveat to this. Imagine you are changing your time from 02:00PM to 11:00AM. You would go from left to right, and as soon as you change 02 hours to 11 hours, the javascript validation fails as it becomes 11:00PM and the value is not able to update.
Either you will have to write a convoluted way to get around all the edge cases, or the users will have to find a weird way to change their time. This is why this is generally a bad idea to validate on every input like this, and instead you can validate it when you submit the form, or onfocusout and let the user know by appropriate styling.

Dynamically Change colour/css styling of Disabled text boxes based on boolean value

<label [invalid]="false" invalidText="" placeholder="Placeholder text">
Middle names (optional)
<input ibmText [attr.disabled]="isApplicationLocked" [invalid]="false" placeholder=""
(keyup)="applicantControlValueChanged()" formControlName="PersonMiddleName">
<label>
In my angular project (using typescript). I have a Boolean called "isApplicationLocked". When this boolean is true, it will disable the text box and not allow the user to edit the text. However, not all portions of the textbox are greyed out. The border and label still remain as black. How am I able to dynamically change the colour of all attributes in the text box, based on this value?
I am also using scss
First, you add the isApplicationLocked variable into the form group.
this.formGroup = this.formBuilder.group({
PersonMiddleName: new FormControl(
...
),
disabled: this.isApplicationLocked
});
And then, you need to create a subscription for changing of this value.
this.formGroup.get("disabled").valueChanges.subscribe(value => {
this.changeDisabledState(value);
});
Here changeDisabledState function is to change the disabled state of the input control.
changeDisabledState(value: boolean): void {
if(value){
this.checkoutForm.controls['PersonMiddleName'].enable();
}else{
this.checkoutForm.controls['PersonMiddleName'].disable();
}
}
Use the :read-only CSS pseudo-class, to change the style for readonly mode on input or textarea.
input:read-only,
textarea:read-only {
background-color: #black;
}
https://developer.mozilla.org/en-US/docs/Web/CSS/:read-only

how to highlight the words which are invalid in input given by a user

how to highlight only the words which are invalid in input given by a user where i can make my custom invalid check function.
e.g
hello this is very good and very nice.
suppose this is the input by the user and suppose i want to highlight "very" and "this" or any other custom word.
I have tried putting html tag inside value but html does not parses inside value attribute of input tag.
Try using variable.split() in reading the input. Store it in array using loop and check for errors and highlight
You cannot simply put html tags in input. To enable "rich text" capabilities, you'll have to use the contenteditable HTML attribute, like so...
const words = [/(very)/gi, /(nice)/gi]
const highlightInput = () => {
const richInput = document.getElementById('rich-input')
let text = richInput.innerText
words.forEach(x => {
text = text.replace(x, '<span class="highlighted">$1</span>')
})
richInput.innerHTML = text
}
document.getElementById('highlight').addEventListener('click', highlightInput)
#rich-input{
border:1px solid #000;
padding: 5px;
}
.highlighted{
color:red;
text-decoration:underline;
}
<div>
<input type="button" value="Highlight!" id="highlight" />
</div>
<label>Enter your text below:</label>
<div id="rich-input" contenteditable="true">Hello this is very good and very nice</div>

AngularJs - how to support a textbox with hyperlinks

I'm new to Angular but I'm trying to implement a textbox that allows users to enter in links. I only want to support links, and otherwise I want to block all html from being presented as such. I could theoretically use something other than a textarea, but my requirements are that it must be bound to a variable in my scope (right now with ng-model) and I cannot accept html tags other than '< a >'
Here is my example plnkr
In the example, I would like the second seeded item to display as a link, blue and underlined. However, the third item should display as it is currently shown (without interpreting it as html).
HTML:
<textarea maxlength="160" ng-model="val.text"></textarea>
<div class="btn" ng-click="submit()">Submit</div>
<br><br>
<div ng-repeat="item in items">
{{display(item)}}
</div>
JS:
$scope.submit = function() {
if (!$scope.val.text) return
$scope.items.push($scope.val.text);
}
$scope.display = function(txt) {
return txt;
// something here? if txt contains <a> and </a> indicate
// that we should display as html
}

how do i set property of text box to UpperCase

I use following style attribute so when i will start typing in text box suppose 'railway'then it should get enter in text box like 'RAILWAY' without pressing CapsLock
<input type = "text" class = "normal" name = "Name" size = "20" maxlength = "20"> <img src="../images/tickmark.gif" border="0" style='text-transform:uppercase'/>
but I am not getting desired output by using this attribute
The best method would be to change the styling on your form to display uppercase:
input.normal
{
text-transform:uppercase;
}
SEE EXAMPLE
However this will not actually convert the string to uppercase, just style it to appear this way.
Therefore then when the data is submitted, use whatever server side language to convert the string to uppercase for purposes of storing in the database etc. For example with .NET you would do:
str.ToUpper();
You can accomplish this using CSS, if you only care about stylistic aspect:
.normal { text-transform: uppercase; }
If you need the text itself to be in all-caps (which is probably what you meant, sorry), combine with a bit of jQuery (it can be done without jQuery, too, but what's the point in that?):
$('.normal').change(function() {
$(this).val($(this).val().toUpperCase());
});
Example: http://jsfiddle.net/HackedByChinese/QwSSe/1/
You need to put your text transform in your Input tag, not your Image tag. Like this.
<input type = "text" class = "normal" name = "Name" style="text-transform:uppercase;" size = "20" maxlength = "20">
<img src="../images/tickmark.gif" border="0"/>