To create custom attribute on input html element in Aurelia - aurelia

I want to create a custom attribute input-format
I can assign two values to the attribute that would enable me to clean the input string or to trim input string.
Like below:
For value clean:
Trying to achieve declaring as below
<input
type="text"
placeholder="enter text with illegal characters"
value.bind="dirtyString"
input-format= "format : clean"
/>
The above should result me with the below embedded into the input element:
<input
type="text"
placeholder="enter text with illegal characters"
value.bind="dirtyString | cleanString & updateTrigger:'blur'"
keypress.delegate="keypress($event)"
/>
Similarly for trim
<input
type="text"
placeholder="enter your name"
value.bind="Name"
input-format= "format : trim"
/>
should result in:
<input
type="text"
placeholder="enter your name"
value.bind="Name | trimString & updateTrigger:'blur'"
/>
where cleanString, trimString, are value converters and keypress function which are already declared as needed. I need help with creating custom attribute as I am not sure of getting the current value bound to an html input element and also reassigning that to have all the above value converters and a function.
Can anyone please help me on achieving this? Appreciate your input and help.
This is where I stand:
import * as au from "aurelia-framework";
#au.autoinject
#au.customAttribute("input-format")
export class InputFormat {
constructor(element: Element) {
this.element = element;
}
#au.bindable
format: string;
formatChanged(name: string, newValue: string, oldValue: string) {
// need to have case statements
switch(name){
case 'clean':
// to assign the relevant value converter and the 'value' is to be passed into
// this assigment should result something like below
// <input
// type="text"
// value.bind="Name | cleanString & updateTrigger:'blur'"
// keypress.delegate="keypress($event)"
// >
break;
case 'trim':
// to assign the relevant value converter the 'value' is to be passed into
// <input
// type="text"
// value.bind="Name | trimString"
// >
break;
default:
// to leave the assigment as is
break;
}
}
// the select list
element: Element;
val: any;
}
here is the link where I am trying to put things together:
sand box link

Related

Vuelidate - Accept 'null' or empty string as valid

I am currently using Vuelidate for a form. There is an input field where the user is allowed to leave it in blank, which is an optional field.
Minimum value, if entered, should be 0 or higher, but If I leave it empty, it will still throw the error. Validation works well for numbers, it executes the error class when entered value is below 0.
Summary: I need to have minValue(0) but also nullable possibility.
I currently have this:
validations: {
company_name: {
minValue: minValue(0)
}
}
Template looks like this:
<input
id="company_name"
:value="company_name"
type="number"
min="0"
step="0.01"
:class="{ 'error': v$.company_name.minValue.$invalid"
>

Find duplicate value Vuejs

I have an array of names, and if a user try to update one of them and is duplicate, I want to do something (error message) The problem is that is always duplicate. Pname will be changed on every keypress. I am not sure how to store the initial array and to compare with it.
<input
v-model="Pname"
type="text"
class="form-control"
/>
for(let element of this.customer_names){
if(this.Pname == element.name){
duplicateValue = +1;
}
}
You can do something as simple as:
if(this.customer_names.indexOf(this.Pname) != -1) {
// there is a duplicate somewhere
}
Put that code in your change/key-up event listener
You can use #blur like this:
<input
v-model="Pname"
type="text"
class="form-control"
#blur="findDuplicate"
>
function findDuplicate () {
if(this.customer_names.indexOf(this.Pname) != -1) {
// There is a duplicate
}
}
So, by this when you click outside, after you are done with typing, it will run that findDuplicate function.

v-model on input does not dynamically change when passed in a function

I don't know where it went wrong in here.
gets the desired number of textarea
<input type="number" min="0" v-model="columnNum">
<button #click="addTextArea(columnNum)">ok</button>
then push it to an array inside another array
addTextArea(a){
var colArray = [];
for(var i=1; i<=a; i++){
colArray.push({col_num : i , description : "edit me"})
}
this.all.col = colArray;
},
and display it like this
<textarea v-for="textareaCol in all.col" type="text" class="form-control" v-model="textareaCol.description"></textarea>
it doesnt work the first time you click 'ok', but if you try to input another value after you click 'ok', it triggers the function and run it. it seems that its not passing the value when it triggers the addTextArea function

aurelia-validation with custom element

I created an input form with aurelia-validation plugin which worked perfectly.
Now I created a custom element to replace the input type textbox.
I'm trying to validate the new custom element value, by setting the value attribute with the "validate" keyword - but the custom element input value isn't validated.
It seems like the Validation Controller is not binded to the custom element.
The bindings array of the Validation Controller doesn't contains the custom element.
Maybe this is related to the actions that should trigger the validation (blur\focus out), so I added dispatching of blur event, but it still doesn't work. As mentioned - it worked perfectly when it was a regular element.
Here is the relevant code (un-needed code was removed):
custom element template:
<template>
<label>
${title}<input name.bind="fieldName"
title.bind="title" focusout.trigger="focusoutAction()" />
</label>
</template>
custom element relevant viewmodel code:
#bindable onFocusout;
...
bind(bindingContext) {
var input = this.element.getElementsByTagName("input")[0];
input.type = this.customType || "text";
input.placeholder = this.placeHolder || "";
//input.value.bind = bindingContext.registration.firstName & validate;
}
...
focusoutAction() {
var customEvent = new CustomEvent("blur");
this.element.dispatchEvent(customEvent);
this.onFocusout();
}
Relevant container(parent) view code:
<form-input name="firstName" id="firstName" title="First Name" bind-
value="registration.firstName & validate" field-name="firstName" on-
focusout.call="validateInput()" />
And the relevant viewmodel code:
ValidationRules
.ensure(r => r.firstName).displayName('first
name').required().withMessage(`\${$displayName} cannot be blank`)
.satisfiesRule('FirstNameValidation')
.ensure(r => r.lastName).displayName('last
name').required().withMessage(`\${$displayName} cannot be blank`)
.satisfiesRule('LastNameValidation')
validateInput() { this.getValidationError(event.target.name); }
getValidationError(propertyName) {
let error = this.getValidationFirstError(propertyName);
....
}
getValidationFirstError(propertyName)
{
if (this.controllerToValidate.errors !== null &&
this.controllerToValidate.errors.length > 0) //This is 0 !!!!!
}

RIOT.JS: Showing an element depending on input value

I would like to do something like this:
<input type="text" value={ value1 } >
<input if={ value1 != ''} type="text">
So, adding to DOM the second input when the first input has any value different than empty. I know 2-way data binding is not supported by Riot.js
I have tried to do the following:
<input ref="first" type="text" >
<input if={ this.refs.first.value != '' } type="text">
But it does not work.
You are correct, Riot does not do 2-way data binding for reasons I'll leave to the reader to research. It's fascinating stuff, but in my opinion, most web development can be made drastically simpler by following a few simple patterns. Riot is great for this reason. Simply put, the tag is just markup with event listeners that can update the tag.
<my-tag>
<input name='username' type='text' onKeyup={ checkVal } value={ opts.val }>
<input if={ usernameEntered } name='password' type='password'>
<script>
this.checkVal = (event) => {
this.usernameEntered = event.target.value !== ''
// this.update() is implicitly called in event listeners
}
</script>
</my-tag>
In your case (I don't know your exact use case), you may want to populate the first input element with a value passed into the tag (opts.val). Then we can assign some variable (usernameEntered) in an event listener (checkVal) and update the tag.
See Riot JS Guide for more detailed examples