Aurelia repeater: model.bind is not working for radio buttons - radio-button

I am creating a set of radio buttons in Aurelia with the code like this:
<div repeat.for="option of options">
<input type="radio" id="${option}_id" name="radio_options" model.bind="option" checked.bind="optionValue"/>
<label for="${option}_id" id="${option}_label">${option}</label>
</div>
However, doing it this way I discovered that model.bind is not working - the optionValue in corresponding class is not populated when radio button is checked. Similarly when some value is assigned to optionValue in the class, the appropriate radio button is not checked. I found this happening only with repeater. Options are numbers in my case. Could you please help me to find out what may be wrong here?

The first problem is that model.bind should be used when working with objects. Since you're working with a primitive type, you should use value.bind instead.
The second problem is that input values are always strings, so when setting an initial value, it must be a string. For example:
Html:
<template>
<div repeat.for="option of options">
<input type="radio" id="${option}_id" name="radio_options" value.bind="option" checked.bind="optionValue"/>
<label for="${option}_id" id="${option}_label">${option}</label>
</div>
<p>Selected Option: ${optionValue} </p>
</template>
JS:
export class App {
options = [ 1, 2, 3, 4 ]
optionValue = '3';
}
If you really want to use int in your view-model, you can create a ValueConverter to convert the value to int when passing it to/from the view. For instance:
export class AsIntValueConverter {
fromView(value) {
return Number.parseInt(value);
}
toView(value) {
return value.toString();
}
}
Usage:
<input type="radio" id="${option}_id" name="radio_options" value.bind="option" checked.bind="optionValue | asInt"/>
Running Example https://gist.run/?id=1465151dd5d1afdb7fc7556e17baec35

Related

Blazor problem connecting the UI with the code

I'm using Blazor Server application in Visual Studio 2019. In the .razor page I have:
<div class="container">
<div class="row">
<div class="col-md">
<label for="ConnectionStringEdit" id="Label1">Connection String for destination</label>
</div>
<div class="col-md-7">
<input type="text" id="ConnectionStringEdit" name="ConnectionStringEdit" text=#ConnectDestination spellcheck="false" style="width: 585px; height: 26px;" class="form-control">
</div>
<div class="col-md-auto">
<input type="submit" id="btnConnect" name="btnConnect" value="Connect" class="btn btn-primary" #onclick="Connect1">
</div>
</div>
</div>
now in the code part I have
#code {
private string ConnectDestination { get; set; } = "";
private void Connect1()
{
if (ConnectDestination.Length > 0)
{
// do something
}
}
}
When I insert something in the Input and I press the button, ConnectDestination doesn't take the value of the Input Control. So this last If condition is never true. How do I get the inserted value of the Input control named ConnectionStringEdit?
Thanks
It should be #bind-value="#ConnectDestination"
you could also use the short directive #bind instead:
#bind="#ConnectDestination"
Note: All the input element's types are bound through the value attribute of the element.
Note: Both #bind-value and #bind are compiler directive instructing the compiler to emit code, behind the scene, that enables two way data-binding between a variable and an Html tag. The compiler create a two-way data binding by binding a variable to the value attribute of the element, something equivalent to this:
value="#ConnectDestination", which creates a one direction binding from the variable to the bound element. The compiler also creates an event call back which enables binding from the element to the variable, something equivalent to this:
#onchange="#((args) => ConnectDestination = args.Value?.ToString())"
This means that you could do that yourself, if you wish to have more control over the binding. You'll usually do something like this:
value="#ConnectDestination" #onchange="OnChange"
And define the call back method like this:
private void OnChange(ChangeEventArgs args)
{
// Note that it is your responsibility to update the
// ConnectDestination variable:
ConnectDestination = args.Value?.ToString());
}
Note: This is wrong:
<input type="submit" id="btnConnect" name="btnConnect" value="Connect" class="btn btn-primary" #onclick="Connect1">
The type attribute of the input element should be set to button:
<input type="button"
Blazor App is an SPA... meaning no submit. The only place you use the "submit" button is when you use the EditForm component, and even then the "submit" action is intercepted and canceled by the Blazor.
You can try
<input type="text" id="ConnectionStringEdit" name="ConnectionStringEdit" #bind=#ConnectDestination spellcheck="false" style="width: 585px; height: 26px;" class="form-control">
or
<input type="text" id="ConnectionStringEdit" name="ConnectionStringEdit" value="#ConnectDestination"
#onchange="#((ChangeEventArgs __e) => ConnectDestination = __e?.Value?.ToString())" spellcheck="false" style="width: 585px; height: 26px;" class="form-control">

Binding getter array to checkbox group

I have a two page form so I am trying to mix submitting data to the server as well as making use of vuex. So on page one, I have a simple form which contains a group of checkboxes (removed layout and styling to reduce code)
<b-form #submit.stop.prevent="onSubmit">
<b-form-group>
<input v-model="$v.form.checkboxGroup.$model" type="checkbox" name="checkbox1" value="1">
<input v-model="$v.form.checkboxGroup.$model" type="checkbox" name="checkbox2" value="2">
<input v-model="$v.form.checkboxGroup.$model" type="checkbox" name="checkbox3" value="3">
</b-form-group>
<button class="btn try-btn" type="submit">Submit</button>
</b-form>
Essentially, when submitted, I send the form data to my repository so it can be saved on the backend. If this is successful, I call the following method
handleSubmitSuccess (response) {
if (response.data.action === 'next_step') {
this.$store.dispatch('createCheckboxData', this.$v.form.$model)
return
}
}
This method sets the checkbox data in my store and routes the user to the next page (removed this part). So all of this is fine, seems to work well.
So when on page two, I have a button that can take you back to page one. My idea is that if this happens, I use the previously checked data in the store to auto check the previously selected checkbox. As such, on page one I added a computed method
computed: {
checkboxData () {
return this.$store.getters.checkboxData
}
}
Now if I output checkboxData to the console, it seems to be an Observer object
[{…}, __ob__: Observer]
0:
checkboxData: Array(2)
0: "1"
1: "3"
length: 2
So the above shows that previously, the first and second checkboxes were checked.
My question is how can I now use this data to auto-check my checkboxes. I have seen some examples online, but they do not seem to work.
Thanks
The way you use Vue is a little different to me so you might have to change this but, basically, you can set your v-model to whatever array is set in the Vuex store and it will set those checkboxes to true:
new Vue({
el: "#app",
data: {
checkbox: [],
vuexData: ['1', '3']
},
mounted() {
this.checkbox = this.vuexData;
}
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<input v-model="checkbox" type="checkbox" name="checkbox1" value="1">
<input v-model="checkbox" type="checkbox" name="checkbox2" value="2">
<input v-model="checkbox" type="checkbox" name="checkbox3" value="3">
{{ checkbox }}
</div>

how to get a reference to the specific v-model in form

I'm new to Vue2 and am trying to to get a reference to a model's value in a form to be passed to a method. I have:
<div v-for="n in maxLength">
<input v-model='price.matrix_prices[n]' /><div #click="fillPrices(?)">set all to this price</div>
{{n}}</div>
The matrix_prices is a hash with specified values. Lets say someone fills in 8 in the input model, how would I get a reference so that ? would be eight?
Do you have access to n in the function as below?
<div v-for="n in maxLength">
<input v-model='price.matrix_prices[n]' />
<div #click="fillPrices(n)">set all to this price
</div>
{{n}}
</div>
If yes write the function like this:
methods: {
fillPrices(n) {
var data = this.price.matrix_prices[n];
//do something with the data
}
}

Can I debounce a checkbox input in Aurelia?

I'm trying to use the debounce binding behaviour on a list of checkboxes, but it doesn't seem to be working the way I expect (I'm not sure if you can even debounce a checkbox):
<label repeat.for="v of values">
<input type="checkbox" value.bind="v" checked.bind="checkedVal & debounce:1000"> Checkbox value "${v}"
</label>
clicking on any of the checkboxes results in the checkedVal array updating immediately, whereas it works as I expect for a normal input:
<input type="text" value.bind="textVal & debounce:1000"/>
Can I debounce a checkbox input?
Here's the full code, with a GistRun here.
app.html:
<template>
<h1>Checkbox bind debounce</h1>
<form>
<label for="text">text input with debounce:1000 </label>
<input type="text" value.bind="textVal & debounce:1000"/>
<div repeat.for="v of values">
<br/>
<label>
<input type="checkbox" value.bind="v" checked.bind="checkedVal & debounce:1000"> Checkbox value "${v}"
</label>
</div>
</form>
<br/>
<p>Text value: ${textVal}</p>
<p>Checked values:</p>
<p repeat.for="v of checkedVal">${v}</p>
</template>
app.js:
export class App {
values = [1, 2, 3];
checkedVal = [];
}
Thanks!
At this time, it's not supported. The debounce binding behavior controls the rate at which the checkedVal property is assigned. In a checked binding, the property isn't assigned, the array instance referenced by the property is mutated with push and splice which circumvents the debouncing in the binding expression.

asp-for tag adds required field validation on checkbox in asp.net core

I have asp.net core application and im trying to add simple checkbox without any validation. Checkbox is bound to boolean property on model. Below is the code
Model
public class MyModel
{
public bool IsEmployee { get; set; }
}
cshtml
<form>
<div>
<label asp-for="IsEmployee">Is Employee</label>
<input type="checkbox" asp-for="IsEmployee"/>
</div>
<button id="btnSave" class="btn btn-primary" type="button">Save</button>
</form>
<script src="~/js/test.js"></script>
javascript
$(function () {
var kendoValidator = $('form').kendoValidator().data("kendoValidator");
$('#btnSave').click(function () {
if (kendoValidator.validate()) {
alert('true');
}
else {
alert('false');
}
})
})
I am using asp-for tag helper on input element. Note that IsEmployee property DOES NOT have [Required] attribute. But because of asp-for tag helper the rendered html has data-val-required and data-val attributes on input element. It also adds one more hiddden input element with same name.
Below is rendered html.
(also note that i think it only happens when input type is checkbox. for textboxes its working fine)
<form novalidate="novalidate" data-role="validator">
<div>
<label for="IsEmployee">Is Employee</label>
<input name="IsEmployee" id="IsEmployee" type="checkbox" value="true" data-val-required="The IsEmployee field is required." data-val="true">
</div>
<button class="btn btn-primary" id="btnSave" type="button">Save</button>
<input name="IsEmployee" type="hidden" value="false">
</form>
I am using kendovalidator as well which adds data-role="validator" on form element.
Issues
There are 2 issues here
1> As soon as i click on check the box error message appears as The IsEmployee field is required.
2>kendoValidator.validate() method always returns false regardless of checkbox is selected or not.
Demo here JSFiddle
Update 2
We cannot bind nullable bool to checkbox. I am using asp.net core. I am not sure what the equivalent syntax in asp.net core for the suggestion here which is valid for classic asp.net
Add data-validate="false" to the checkbox input. The kendoValidator will ignore all inputs with that attribute set to false.
<input type="checkbox" asp-for="IsEmployee" data-validate="false" />
If you don't wan't the default generated html you have 2 choices.
Don't use it ! You are not forced to use the tag helpers, they are there for when you do need other html attributes generated. In this case just use < input name="IsEmployee" ...>
Change the way asp-for behaves for your checkbox. You can do this be either creating your own IHtmlGenerater or by extending the DefaultHtmlGenerator and overriding GenerateCheckBox and possibly GenerateInput and then registering it with something like services.TryAddSingleton();
Hope this helpes you.