Validate a form with fields wrapped in another components in Aurelia - aurelia

I'm wondering if I can validate a form with input fields that are wrapped in another components.
Something like this:
<template>
<require from="./inpWrap"></require>
<form submit.delegate="submit()">
<div class="form-group">
<inp-wrap value.bind="firstName & validate"></inp-wrap>
</div>
<button type="submit" class="btn btn-primary">Submit</button>
</form>
</template>
Here's the full gist: https://gist.run/?id=f94dd7502141f865468465ef25c9e5a1
Visually, in this example, the validation will run only on running the .validate() method (by clicking on the submit button) for the wrapped element.
Would it be possible to have the same validation behaviour for the component-wrapped elements?

Related

Vue - Form inside another form and submit event trigger

I have a form inside another form and I want to prevent default action for both forms on submit event:
Vue component:
<template>
<div v-show="isActive" #submit.prevent="onSubmit">
<slot :form="form"></slot>
</div>
</template>
Child:
<form method="POST" action="/update-user">
// form fields part 1
<form method="GET" action="/delete-user">
<button type="submit">
<span>{{ $is_deleted ? 'Cancel Delete' : 'Delete Account' }}</span>
</button>
</form>
// form fields part 2
<button type="submit">
<span>Update</span>
</button>
</form>
When I submit update-user form then the component onSubmit method is hit and prevents default action. However, when I hit delete-user form then the onSubmit method is not hit and the page gets reloaded.
If I get the second form outside of the first one, then it works.
How I can trigger onSubmit method for the second form?
No, This looks like nested form and it violates the spec as outlined in Prohibitions.
Form must not contain another form. I think you should design your app differently. May be two different forms. Or just use plain ajax request as its a vue app anyway?

Vue.js: Loading template (or div) when user clicks button?

So I currently have a template sitting in a ".vue" file like so:
<template>
<div id="dataAttachToMe"></div>
</template>
I don't want this to load, unless a user clicks a button, something like
<button #click="loadTheTemplateAbove">See Data</button>
I've tried using this example:https://v2.vuejs.org/v2/guide/conditional.html#Controlling-Reusable-Elements-with-key. But it says something like "Component template should contain exactly one root element" in the error message.
I need more than a show/hide here I think, something that can initiate the template dynamically.
<template>
<div id="data">
<button #click="loadTemplate">Load the template</button>
<div v-if="buttonClicked">
<div id="dataAttachedToThisDiv"></div>
</div>
</div>
</template>
The error you are getting, means that there is more than one root element inside <template></template> tag.
It is required in Vue.js (and other template based frameworks/libraries) to have only one root element.
This will NOT work:
<template>
<div id="dataAttachToMe"></div>
<button #click="loadTheTemplateAbove">See Data</button>
</template>
This will work:
<template>
<div id="someRootDiv">
<div id="dataAttachToMe">Some data</div>
<button #click="loadTheTemplateAbove">See Data</button>
</div>
</template>
Here is a code example (App.vue) of what you are trying to achieve:
Basic idea: we have to create a variable, that will be changed upon button click. We add v-if directive that depends on that variable and will handle element's visibility.
Welcome to StackOverflow. When you get the error Component template should contain exactly one root element it means that you can only have one root element in your template. You can fix that error by wrapping everything in a blank div like so
<template>
<div>
<template v-if="loginType === 'username'">
<label>Username</label>
<input placeholder="Enter your username">
</template>
<template v-else>
<label>Email</label>
<input placeholder="Enter your email address">
</template>
</div>
</template>
Please edit your post and place you <script> tag. Conditional Rendering requires a data field of a boolean that you can place in your if statement on your template
<template>
<div>
<div v-if="show">{{message}}</div>
<div v-if="#show">Not Showing when show is set to false</div>
<button v-on:click="show = true">Show</button>
</div>
</template>
<script>
module.exports {
data: function () {
message: 'Hello Vue!',
show: false
}
}
</script>

vuejs component that inherits parent's context

Let's start from this
<div class="form-group" :class="{'has-error':determineError('content')}">
<label>Content Label</label>
<div class="mandat">*</div>
<input v-model="form.content" name="content" v-validate="'required|min:5|max:100'" class="form-control">
</div>
The first thing I would like to obtain is to put this piece of code somehow inside a component, something like this:
Vue.component('form-group', {
...
template: `<div class="form-group" :class="{'has-error':determineError('content')}">
<label>Content Label</label>
<div class="mandat">*</div>
<input v-model="form.content" name="content" v-validate="'required|min:5|max:100'" class="form-control">
</div>`
});
As you can see I still have the input field right there. What I would like to do is pass any piece of code instead and the current component must inherit parent's context.
Something like
<form-group>
<template>
<input v-model="form.content" name="content" v-validate="'required|min:5|max:100'" class="form-control">
</template>
</form-group>
How can this be achieved? Notice that I still use parent's context. If using parent's context is not possible, then how can I achieve this in the simplest way?
You have to use slots, which are expanded in the component template with the contents passed by the parent.
In the form-group component:
<template>
<div class="form-group" :class="{'has-error':determineError('content')}">
<label>Content Label</label>
<div class="mandat">*</div>
<slot v-bind:form="form"></slot>
</div>
</template>
You can also add a fallback content inside the <slot> (a default input maybe). Note we are passing the context for the slot contents (see Scoped Slots).

Vuelidate how to conditionally disable submit button

How can I conditionally disable the submit button of my Vuelidate form if all the fields don't meet the required criteria?
I tried the below but :disabled will only accept the word disabled in there.
<form>
<ol>
<li class="inputQuestion" v-bind:class="{ 'error': $v.user.username.$error }">
<label>Username:</label>
<input v-model.trim="user.username" #input="$v.user.username.$touch()" />
</li>
<li class="inputQuestion" v-bind:class="{ 'error': $v.user.password.$error }">
<label>Password:</label>
<input v-model.trim="user.password" #input="$v.user.password.$touch()" />
</li>
<li class="submission">
<button #click.prevent="submitForm" :disabled="$v.form.valid()">Sign In</button>
</li>
</ol>
</form>
Currently, you are binding disabled to the value returned by $v.form.valid(), which will only be run once when the component's template is rendered and won't change after that point.
From the Vuelidate documentation, it looks like you are provided a $invalid property for the form model which:
Indicates the state of validation for given model. becomes true when any of it's child validators specified in options returns a falsy value. In case of validation groups, all grouped validators are considered.
Use that instead:
<button #click.prevent="submitForm" :disabled="$v.form.$invalid">
Another way to disable/enable the submit button with vuelidate:
<button #click.prevent="submitForm" :disabled="$v.$anyError">

Check box is not coming in Request.Form (NameValueCollection)

I create one Method in MVC 4.0 which taking the Request.Form (Namevaluecollection) in Form. I faced below issue in checkbox and radio button.
I added dynamically checkbox or radio button with below code, and I set the form value collection as "NameValueCollection formsCollection = Request.Form" in one of my controller method but that checkbox or radio button is not coming in "formsCollection.AllKeys" while other control like text box, text area, dropdown will work properly.
<form>
<div class="divLeft div1" id="div83ac0fad-41d5-40e5-99cd-f99ea8877b04">
<div class="control-group">
<label class="control-label">Checkbox 2</label>
<div class="controls">
<div id="cfCheckbox">
<label>Option 1</label>
<input type="checkbox" id="checkbox83ac0fad-41d5-40e5-99cd-f99ea8877b04" name="checkbox83ac0fad-41d5-40e5-99cd-f99ea8877b04">
<label>Option2</label>
<input type="checkbox" id="checkbox83ac0fad-41d5-40e5-99cd-f99ea8877b04" name="checkbox83ac0fad-41d5-40e5-99cd-f99ea8877b04">
</div>
</div>
</div>
</div>
</form>
You're having id="checkbox83ac0fad-41d5-40e5-99cd-f99ea8877b04" on both check-boxes and the main div. IDs in HTML are supposed to be unique.
Remove the IDs on the checkboxes. This should fix your problem.
FormsCollection uses Name for binding, not ID. So you don't really need your elements to have IDs.