Require and Regex with vee-validate - attributes

I'm attempting to set a required and regex attributes with vee-validate. The regex bit works fine, but as soon as I add the required attribute the entire control disappears from the form.
This works fine (fiddle), but missing required attribute (multiline for easier reading):
<input
v-validate="{ regex:/^((\d{3})[ -]|(\d{3}[ -]?)){2}\d{4}$/ }"
:class="{'input': true, 'is-danger': errors.has('phonenumber') }"
class="input is-primary"
name="phonenumber"
type="text"
placeholder="404-555-1212"
> <!-- end input -->
This causes the entire form to disappear (fiddle) (multiline for easier reading):
<input
v-validate="{ required|regex:/^((\d{3})[ -]|(\d{3}[ -]?)){2}\d{4}$/ }"
:class="{'input': true, 'is-danger': errors.has('phonenumber') }"
class="input is-primary"
name="phonenumber"
type="text"
placeholder="404-555-1212"
> <!-- end input -->
I've tried using a comma to separate vee-validate attributes, but this also fails in the same manner.
What am I missing?

I needed to include required: true, in order for the attribute to work correctly.
Like this:
<input
v-validate="{ required: true, regex:/^((\d{3})[ -]|(\d{3}[ -]?)){2}\d{4}$/ }"
:class="{'input': true, 'is-danger': errors.has('phonenumber') }"
class="input is-primary"
name="phonenumber"
type="text"
placeholder="404-555-1212"
> <!-- end input -->

Related

How to get structured object using POST endpoint in SvelteKit?

when I'm using the POST endpoint from Sveltekit, I get a "flat" object as output. How can I get a "structured" Object instead ?
Let's assume the following code:
index.svelte
<div class="container">
<form method="post">
<label for="firstname">Firstname</label>
<input type="text" name="firstname" />
<label for="lastname">Lastname</label>
<input type="text" name="lastname" />
<label for="dog">Dog 1</label>
<input type="text" name="dog" />
<label for="dog">Dog 2</label>
<input type="text" name="dog" />
<!-- ... -->
<button>Save</button>
</form>
</div>
index.js
export async function post({request}){
const data = Object.fromEntries(await request.formData());
console.log(data);
return{}
}
Ouput (what I'm calling "flat" object)
{ firstname: 'foo', lastname: 'bar', dog: 'teckel', dog: 'labrador' }
Instead of that output, how should I proceed to get the following one in my index.js
Expected output:
{
firstname: 'foo',
lastname: 'bar',
dogs: [ { dog: 'teckel' }, { dog: 'labrador' } ]
}
There are libraries that can perform a transform like this more or less automated. Some use conventions in the field names to parse the data into arrays and nested structures, others additionally use schemas to do type conversions or validation. E.g. to achieve an array of objects like this, one might set the names like this:
<label for="dog">Dog 1</label>
<input type="text" name="dogs[][dog]" />
<label for="dog">Dog 2</label>
<input type="text" name="dogs[][dog]" />
The [] Indicates that the field is part of an array, [dog] indicates that a property called dog is set on the element (.dog would also be reasonable).
So instead of calling Object.fromEntries you have to either parse the data yourself or find a library that does it for you. (Note that StackOverflow is not a place for library recommendations.)
Personally, I would avoid the synchronous form post and send JSON asynchronously instead, that way you can send in a fixed structure and receive that exact structure. Of course this requires binding/reading the form values yourself.

How to make AUI validation apply only when a check box is selected?

I have fields in an aui form that I only want to be required when a corresponding checkbox is selected, otherwise they're not required. I'll enable these input fields using <aui:script> once the check box is enabled and only then aui validation should work.
I have tried with hiding the <aui:validator> depending condition in script.
How do I enable the validation only if my check box is selected in aui?
<aui:form action="" method="post">
<aui:input type="checkbox" name="employeeId" id="employeeId"></aui:input>
<div id="employeeDetails">
<aui:input type="text" name="name" id="employeeId2">
<%
if (true) { //default i kept true how to check this condition on check box basic
%>
<aui:validator name="required"' />
<%
}
%>
</aui:input>
<aui:input type="text" name="email" id="employeeId3">
<%
if (true) {
%>
<aui:validator name="required" />
<%
}
%>
</aui:input>
</div>
<aui:button-row>
<aui:button type="submit" />
</aui:button-row>
</aui:form>
<aui:script>
AUI().use('event', 'node', function(A) {
A.one('#employeeDetails').hide(); // to hide div by default
var buttonObject = A.all('input[type=checkbox]');
buttonObject.on('click', function(event) {
if (A.one("#<portlet:namespace/>employeeId").attr('checked')) {
A.one('#employeeDetails').show(); //for checked condition
} else {
A.one('#employeeDetails').hide(); // for non checked condition
}
});
});
</aui:script>
Reference images:
Before enabling the check box
[]
Check box enabled:
[]
This sample if(true) bothers me - it's evaluated server side on the JSP and won't have any effect, since true is always true.
However, your question is well documented within Liferay's documentation: Look for "Conditionally Requiring A Field"
Sometimes you’ll want to validate a field based on the value of
another field. You can do this by checking for that condition in a
JavaScript function within the required validator’s body.
Below is an example configuration:
<aui:input label="My Checkbox" name="myCheckbox" type="checkbox" />
<aui:input label="My Text Input" name="myTextInput" type="text">
<aui:validator name="required">
function() {
return AUI.$('#<portlet:namespace />myCheckbox').prop('checked');
}
</aui:validator>
</aui:input>

Detect Input Focus Using Angular 2+

I'm trying to create an auto-complete list that appears as you type, but disappears when you click elsewhere on the document. How do I detect that a form input is focused using Angular 2. Angular 1 has ng-focus, but I don't think Angular 2 supports that anymore.
<input id="search-box" type="search" class="form-control [(ngModel)]=query (keyup)=filter()>
<div id="search-autocomplete" *ngIf="filteredList.length > 0">
<ul *ngFor="#item of filteredList" >
<li > <a (click)="select(item)">{{item}}</a> </li>
</ul>
</div>
By the way, I used this tutorial as guidance.
There are focus and blur events:
<input (blur)="onBlur()" (focus)="onFocus()">
For those using #angular/material, you can get a reference to the MatInput instance which implements MatFormFieldControl interface exposing a nice focused property.
<mat-form-field>
<input matInput #searchInput="matInput" type="text" />
<mat-icon matPrefix svgIcon="filter" [color]="searchInput.focused ? 'primary' : ''"></mat-icon>
</mat-form-field>
You could also use FocusMonitor from #angular/cdk.
https://material.angular.io/guide/creating-a-custom-form-field-control#focused
focused = false;
constructor(fb: FormBuilder, private fm: FocusMonitor, private elRef: ElementRef<HTMLElement>) {
...
fm.monitor(elRef.nativeElement, true).subscribe(origin => {
this.focused = !!origin;
this.stateChanges.next();
});
}
ngOnDestroy() {
...
this.fm.stopMonitoring(this.elRef.nativeElement);
}
You can use the ngControl directive to track change-state and validity of form fields.
<input type="text" ngControl="name" />
The NgControl directive updates the control with three classes that reflect the state.
State: Control has been visited
ng-touched
ng-untouched
State: Control's value has changed
ng-dirty
ng-pristine
State: Control's value is valid
ng- valid
ng- invalid

angularjs data binding not working on string variable?

I have 2 versions of my code, one is not working and the other it is.
My question is "why the not working one is not working?"
here is the JSfiddle http://jsfiddle.net/fhjF7/
The not working version:
Controller:
function Ctrl($scope) {
$scope.username = "username";
$scope.users = [ "Matteo", "Marco", "Michele" ];
};
HTML:
<h1> Not working example</h1>
<div ng-controller="Ctrl">
<div ng-repeat="user in users">
<input type="radio" ng-model="username" name="usern" ng-value="user" />
<strong>{{user}}</strong>
</div>
<div>selected: {{username}}</div>
</div>
and here is the working one, which is almost identical but replacing the string variable with an object:
Controller:
function usersCtrl($scope) {
$scope.names = {username: "username"};
$scope.users = [ "Matteo", "Marco", "Michele" ];
};
HTML:
<h1> Working example</h1>
<div ng-controller="usersCtrl">
<div ng-repeat="user in users">
<input type="radio" ng-model="names.username" name="username" ng-value="user" />
<strong>{{user}}</strong>
</div>
<div>selected: {{names.username}}</div>
</div>
It is because of the way javascript manages function parameters.
The easy way to understand it is that String, Number, and Boolean parameters are always sent byValue, while Objects and Functions are always sent byRef, that is why when you use the dot inside an ng-model it means you are doing a reference to an object which will propagate, while if you don't use a dot inside the ng-model, you are referencing a String, Number or Boolean which is actually a copy of the real variable.
More information here https://egghead.io/lessons/angularjs-the-dot and https://github.com/angular/angular.js/wiki/Understanding-Scopes
Ng-repeats create their own isolate scopes, so that's why the string is not being preserved as it's not pass by reference. If you want to update the model use
<input type="radio" ng-model="$parent.username" name="usern" ng-value="user" />
$parent gives you access to the parents scope which is outside the ng-repeat and should be the one you want.
The answer for your not working code : http://jsfiddle.net/ashuslove/fhjF7/30/
HTML :
<h1> Not working example</h1>
<div ng-controller="Ctrl">
<div ng-repeat="user in users">
<input type="radio" ng-model="names.usern" name="usern" ng-value="user" />
<strong>{{user}}</strong>
</div>
<div>selected: {{names.usern}}</div> //Changed line here
</div>
The function :
function Ctrl($scope) {
$scope.names = {usern: "usern"}; //Also need to change this
$scope.users = [ "Matteo", "Marco", "Michele" ];
};

Cucumber/Capybara - How to search for a specific button using XPath?

I am trying to figure out how to write an oAuth/Twitter signin feature with Cucumber/Capybara. Part of it, consists in visiting the page: http://www.twitter.com/sessions/new and filling in the username, the password and then clicking on the 'Sign in' button. That last step is not working as expected, the html code for that page looks like this (located in french):
<fieldset class="textbox">
<label class="username">
<span>Nom d'utilisateur ou e-mail</span>
<input type="text" value="" name="session[username_or_email]" autocomplete="on" />
</label>
<label class="password">
<span>Mot de passe</span>
<input type="password" value="" name="session[password]" />
</label>
</fieldset>
<fieldset class="subchck">
<button type="submit" class="submit button">Se connecter</button>
I have a defined the step like this in web.steps (note that I am not using the default capybara driver but capybara-mechanize):
Given /^I sign in$/ do
visit 'http://twitter.com/sessions/new'
fill_in "Username or email", :with => 'xxx'
fill_in "Password", :with => 'xxx'
find(:xpath, 'button[#class="submit button"]')
....
end
The find(:xpath,..) line is not working properly. I tried to put a '/s' (regex for space character) but I still get this error message:
Unable to find '//button[#class="submit\sbutton"]' (Capybara::ElementNotFound)
I also tried:
xpath_for("submit button")
But I get a stack level too deep error!
I am not really confident with my regex/xpath element finding skills so please tell me what is wrong with my code and how I could find that button?
Thanks so much for helping me!
[EDIT]
Turns out the default selector is :css. I changed it to :xpath:
Capybara.default_selector = :xpath
But it still doesn't solve my problem.
What if you try
click_on "Se connecter"
EDIT: Trying in nokogiri (cause capybara uses nokogiri) it doesn't work for me when I use your HTML as is (meaning it doesn't even see the element in the document). But when I enclose everything in a single root node, it works.. don't know if there's an issue with your page HTML or something.. with a well formed page, it "should" work. not sure how much this helps
<html>
<fieldset class="textbox">
<label class="username">
<span>Nom d'utilisateur ou e-mail</span>
<input type="text" value="" name="session[username_or_email]" autocomplete="on" />
</label>
<label class="password">
<span>Mot de passe</span>
<input type="password" value="" name="session[password]" />
</label>
</fieldset>
<fieldset class="subchck">
<button type="submit" class="submit button">Se connecter</button>
</html>
with this HTML, I can just use the xpath
xpath('//button')
Instead:
find(:xpath, 'button[#class="submit button"]')
you should have:
find('button.submit.button')
Above is css, since it's default selector.
If you want solution with XPath look at https://stackoverflow.com/a/11752824/507018, but it's uglier.
If you have the exact match to class of button <button class="submit button">, you can try just the following:
find(:xpath, '//button[#class="submit button"]')
Make sure that you didn't forget the double slash in the beginning of the search string.

Resources