Vue - conditional attribute binding - vuejs2

I am making a form in a Vue component and would like to set the HTML attribute required to an input field based on the value I am having in an object property.
So, for the example, an object that has fields like this:
label:"Name"
required:"1"
type:"textbox"
I need to a set the field to have required attribute in an input tag:
<input class="input is-large" :type="input.type" required>
And for the ones that don't have 1 as a value for that field I don't want a required attribute.
How can I do that in Vue?

You can do it like this:
<input class="input is-large" :type="input.type" :required="obj.required == 1">
Since your object's required property has 1 as a string not number I used == for comparison so that equality is tested after coercion

Related

Non V-bind part of the V-Model

As we know v-model is two way binding. Which means it's combination of V-bind and maybe another attribute which I'm looking for and it updates the data. I have a input which it's value is sometimes custom and sometimes should be read from config based on another parameters.
What I need is an input with a v-bind:value/:value and another for update. I know I can do it with #change and a custom method But I'm looking for something easy, Bottom line is I want V-model without doing v-bind ! Thank You
EDIT: I did it with two input using v-if .
<input type="number" class="item-input" v-if="setting.keto_program=='custom'" id="protein_per_kilo" v-model="setting.keto_program_protein_density">
<input type="number" class="item-input" v-else disabled id="protein_per_kilo" :value="config.keto_programs[setting.keto_program].protein_density">
Anyway doing this using just one input feels better. Thanks
May be you can use computed hook.
computed:{
yourVariable(){
return someVariable/computation
}
}
you can use yourVariable inside your code that will act like v-model without doing v-bind.
yourVariable will be updated as soon as the variables of the return statement of this be changed or updated
Edited:
part of v-model for input tag
<input
v-bind:value="variable"
v-on:input="variable = $event.target.value"
>
or
<input
:value="variable"
#input="variable = $event.target.value"
>
found this via
Vue.js—Difference between v-model and v-bind

Pass info between tag helpers?

I am writing a set of tag helpers that target, for example, <form> and <input> elements. I want to add a custom attribute to the <form> element, and retrieve the value of that attribute in the contained <input> element. So, if my HTML looks like this:
<form xx-value='123'>
<input asp-for='Something' />
</form>
then in my InputTagHelper I would want to retrieve the value 123 that was specified for the xx-value attribute.
Is there a designed-in way to pass data like this between tag helpers?
Consider the case where I have this markup:
<form xx-value='123'>
<input asp-for='Something' />
</form>
<form>
<input asp-for='SomethingElse' />
</form>
In this case, the first invocation of the InputTagHelper would get the value 123. But the second invocation of the InputTagHelper would get a value of 0 since its parent <form> tag didn't specify the magic xxx-value attribute.
The simple answer (which doesn't work for <form> and <input> tags - see blow) is for the "parent" tag helper to store the value in the context.Items dictionary and for the "child" tag helper(s) to retrieve the value from that same dictionary. A Google search for "child tag helper" yields many examples of this scheme.
The problem with this answer (in the context of the OP) is that, for some reason, the <form> tag helper executes after its child <input> tag helper. So, rather than receiving the value from the parent FormTagHelper, the InputTagHelper discovers that the context.Items dictionary is empty.
I created this SO post to ask about that weird behavior.

vee-validate: Is it possible to change the fields-bag-name without changing the current name?

So I want to adapt the Autofill naming for Birthdays. However, this leads to several problems. Now I need to find out if I can force vee-validate to change the name of the field.
To understand it better. This is how it currently looks like:
<select
v-model="day"
id="day"
name="day"
:class="{'invalid' : errors.has('day')}"
v-validate="'required|excluded:0'"
>
<option
:disabled="true"
value="0"
v-text="trans('food.Day')"
/>
<option
v-for="n in 31"
:key="n"
:value="n"
v-text="n"
/>
</select>
<span
class="bar"
:class="{'invalid' : errors.has('day')}"
/>
The name for the select field is "day".
However, according to this, it should be named: "bday-day".
Since I'm using vee-validate, this leads to a rename of the field name to "bday-day". Now errors.has('day')} won't work anymore.
But even if I change this to errors.has('bday-day'), I cannot use my internal watcher for changes in values. I get the error:
Failed watching path: "bday-day" Watcher only accepts simple dot-delimited paths. For full control, use a function instead.
This is because I have to force the same name of the v-model name and vee-validate name. v-model="bday-day" cannot work.
To make it short. My end goal is something like this:
<select
v-model="day"
id="day"
name="bday-day"
:class="{'invalid' : errors.has('day')}"
v-validate="{required: true, excluded: 0, name: 'day'}"
>
<option
:disabled="true"
value="0"
v-text="trans('food.Day')"
/>
<option
v-for="n in 31"
:key="n"
:value="n"
v-text="n"
/>
</select>
<span
class="bar"
:class="{'invalid' : errors.has('day')}"
/>
I would use the name="bday-day" for autofill, but I would set the field name for vee validate to name: 'day'.
Use the data-vv-name attribute
Vee-validate has you covered and you can setup the attribute data-vv-name to achieve precisely this:
<select
v-model="day"
id="day"
name="bday-day"
:class="{'invalid' : errors.has('day')}"
v-validate="'required|excluded:0'"
data-vv-name="day"
>
Now the errors and fields members provided by vee-validate will have a day entry, instead of using the input name bday-day. Thus, if you have a watcher on errors.day, you won't have that nasty problem with the bday-day watching path.
With VeeValidate v3, you have two relevant options you can pass to ValidationProvider, name and vid.
VeeValidate's docs specify that:
name specifies a field name to be used in error messages.
vid is an identifier used for target/cross-field based rules.
From my tests though, vid is also used as the key for fields and errors in the ValidationObserver if provided, and if not, it falls back to name.
As a result, if you have multiple of the same fields in one form, and you're looking to have a unique key name (so that they don't clash and break), then use name purely just for the field name in error messages, and vid to provide a unique ID to be used by ValidationObserver in the fields and errors objects. For example:
<ValidationProvider
name="hours" // used for error messages
:vid="hours-${unique-part}" // unique key to stop clashes
rules="required"
v-slot="{ errors }"
>...</ValidationProvider>
If you're using VeeValidate v3, you can set "name" attribute for the ValidationProvider
<ValidationProvider name="day" rules="required|excluded:0" v-slot="{ errors }">

How to add name value to input element

I am looping a data, from the data, I am adding the name value into the input field, but not at all set. what is the issue here?
My form template:
<form novalidate name="myForm">
<div ng-show="myForm[addVas.name].$error.pattern">Error will come </div>
<div class="form-group">
<input type="text" [(ngModel)]="addVas.input" [attr.disabled]="addVas.disabled ? '' : null " name="{{addVas.name}}" ng-pattern="/^[0-9]/" (blur)="addAdnlVasAfterInput(addVas)" placeholder="Provide value of shipment"
class="form-control">{{addVas.name}} <!--getting value here-->
</div>
</form>
I am not getting throw the error, when user input instead of number in to charters. how to solve that?
Now I have update my name field in to [name]="addVas.name" but I not confirm the name sent, unless if i get error message
There are some confusions between Angular versions. ng-show should be *ngIf or [hidden] with reverse logic, ng-pattern is [pattern]. [attr-disabled] can be [disabled], etc.. Pattern /^[0-9]/ doesn't allow more than 1 digit, I am not sure it was your aim. If you use a property as pattern expression, the use [pattern]="property":
Here is what I suggest:
<form #myForm>
<input type="text" [(ngModel)]="addVas.input"
[disabled]="addVas.disabled" [pattern]="addVas.pattern"
[name]="addVas.name" #input="ngModel">
<div *ngIf="input.errors && (input.dirty || input.touched)" >
<div [hidden]="!input.errors.pattern">
Should be a number
</div>
</div>
</form>
Demo
The properties cannot perform interpolation.
You need to use property binding for setting values to properties.
Try this:
[name]="addVas.name"
instead of
name= "{{addVas.name}}"

Using aurelia variable in html attributes

I want to dynamically set the input datetime step granularity using aurelia binding.
In my time.js:
timeStep = "1";
In my time.html:
The following works correctly:
<input type=datetime-local value="2017-01-01T00:00:00" step="1" value.bind="formParameters.timeFrom" >
${timeStep}
However when I try to set the step using my variable - it doesn't seem to work:
<input type=datetime-local value="2017-01-01T00:00:00" step="timeStep" value.bind="formParameters.timeFrom" >
${timeStep}
You can see I have lost the seconds granularity. When I inspect the element, it comes out as:
<input type="datetime-local" value="2017-01-01T00:00:00" step="timeStep" value.bind="formParameters.timeFrom" class="au-target" au-target-id="37">
Where timeStep should be "1".
To bind any HTML attribute to a property in your viewModel - you need to use .bind.
<input type=datetime-local value="2017-01-01T00:00:00" step.bind="timeStep" value.bind="formParameters.timeFrom">
Aurelia will assume anything in a .bind attribute is a property of your viewModel class and bind them accordingly. You can use .bind on any (as far as I know) HTML attribute.