NgbTypeahead inside the form - forms

I have NgbTypeahead component which uses a list of objects like
export class Example {
name: string;
value: number;
}
as source. It searches by name(value is used as placeholder in another input). I put it inside the form, set the formControlName:
<form [formGroup]="myForm" novalidate (ngSubmit)="save(myForm.value, myForm.valid)">
<input formControlName="name" name="exampleName" type="text" [ngbTypeahead]="search"
[resultFormatter]="formatMatches"
[inputFormatter]="formatMatches"
/>
<!--..some code-->
<br><button type="submit">Submit</button>
</form>
But when I submit it, the selected object of type Example is passed, but if instead I need the value of input, what should I do?
EDITED
Removed ngModel.
The code of formatMatches function:
formatMatches = (value: any) => value.name || '';

Related

Angular 7 FormControl cast input from number to string

I have a FormGroup where I defined a FormControl used this way:
myForm: FormGroup = new FormGroup({
...
code: new FormControl('', Validators.pattern('^[0-9]*$')),
...
});
html:
<mat-form-field class="col">
<input formControlName="code" matInput>
</mat-form-field>
I want this input to be a number, but I can't cast it correctly. I've registered to the vauleChanges event of the form control and did this:
this.myForm.controls['code'].valueChanges.subscribe(d => {
if(this.myForm.controls['code'].valid){
this.myForm.get('code').setValue( +this.myForm.controls['code'].value);
}
})
I've also tried using as number or <number> to cast the value, but if I print the value of my form I get it printed as a string and not a number.
Also, my input shows 0 as default when I load the page:
but I didn't set 0 anywhere and I don't want it to be showing.
I've tried specifying the input type as number, but it shows the arrows and I don't want them to show.
What is the correct way to implement this? I'm a lot confused.
SOLUTION:
You could simply check for changes in model (ngModelChange)="validate()" check for validate() method.
HTML FILE:
<input id="code" class="form-control" [(ngModel)]="code" required (ngModelChange)="validate()">
<div *ngIf="codeValidator.invalid" class="alert alert-danger">
<div *ngIf="codeValidator.errors.required">
Field must not be empty.
</div>
<div *ngIf="codeValidator.errors.pattern">
Only numeric values are allowed.
</div>
</div>
<input type="text" [(ngModel)]="numberValue">
TS FILE:
code = 0;
codeValidator: any = {};
numberValue: any;
validate() {
console.log("Validating");
this.codeValidator = new FormControl(this.code, [
Validators.required,
Validators.pattern('^[0-9]*$')
]);
// You could simply use isNaN
this.numberValue = isNaN(this.code) || this.code === 0 ? '' : +this.code;
}

Correct way to pass different v-model values for same parameter name in POST request

FIDDLE
I am assigning v-model values from a form to parameters in an api. There is only one parameter in the api that I have to assign to both inputs i.e.: name. The name is a required field.
Using v-model values of each input, if the first radiobtn is selected, it will return null for the value of name. If the second radiobtn is selected, the user must enter text into the textbox.
I need to check whether the first radio button has been clicked OR the user entered text in the textbox and successfully pass the value of the first radiobtn or the textbox to the same api parameter (name).
How can I do this?
HTML:
<label class="radiogrp"><input type="radio" v-model="picked" name="default_user" value="reg" >Mary</label>
<label class="radiogrp"><input type="radio" v-model="picked" name="new_usr" value="non-reg"><input type="text" v-model="new_user" ></label>
JS:
/* API parameters
name: (string) or (null)
*/
new Vue({
el: '#app',
data: {
picked: Boolean,
new_user: ""
},
/* Two v-model form values for the one property in the API. */
submit_name(){
this.$http.post("https://jsonplaceholder.typicode.com/users",{
name: this.picked || this.new_user})
// ....then() etc.
}
});
You can add #input event which can update the new_usr field on input changes.
Also you can watch picked variable to make sure if you toggle between radio buttons, new_usr should be reset.
function callMe(){
var vm = new Vue({
el : '#root',
data : {picked : '',new_usr:''},
methods: {
callApi(){
let dataApi={}
if(this.new_usr.length){
dataApi.name=this.new_usr;
}else{
dataApi.name=this.picked;
}
console.log('You selected=', dataApi.name)
}
},
watch:{
picked: function (val) {
this.new_usr='';
}
}
})
}
callMe();
<script src="https://cdn.jsdelivr.net/npm/vue#2.5.11/dist/vue.js"></script>
<div id='root'>
<div>
<label class="radiogrp">
<input type="radio" v-model="picked" name="default_user" value="reg" >Mary</label>
<label class="radiogrp">
<input type="radio" v-model="picked" name="new_usr" value="non-reg">
<input type="text" #input="evt=>new_usr=evt.target.value" :value="new_usr" > </label>
<button #click="callApi">hit me</button>
<span>Picked: {{ new_usr }}</span>
</div>
</div>

Angular2 Forms - ngControl

I'm trying to use ngControl to apply error classes based on user's input.
Somehow, I can't make it to work. I see that appropriate classes are set (line ng-invalid), but when trying to use name.valid (where name is my ngControl) it doesn't work.
html:
<div ngClass="{alert: name.invalid}">
<label for="name">Name</label>
<input ngControl="name" #name id="name" [(ngModel)]="user.name"/>
</div>
</div>
js
export class App {
userForm: any;
user: any;
constructor(
private _formBuilder: FormBuilder) {
this.user = {name: 'Ben'};
this.userForm = this._formBuilder.group({
'name': ['', Validators.required]
});
}
}
I saw on angular.io examples that they do use it like this (just for other cases, like show/hide divs)?
Here's the simple plunker: http://plnkr.co/edit/BKx4yplIOu44tk7Mfolc?p=preview
When input field is empty, I would expect that upper div gets alert class, but that doesn't happen.
In fact there are three things to change in your template:
ngClass should be [ngClass]. Otherwise the value is considered as a string and not as an expression.
#name should be #name="ngForm". Otherwise you reference the DOM element and not the control.
there is no invalid property on controls in Angular2 but only a valid one.
Here is the refactored code:
<div [ngClass]="{alert: !name.valid}">
<label for="name">Name</label>
<input ngControl="name" #name="ngForm"
required id="name" [(ngModel)]="user.name"/>
</div>
Here is the plunkr: http://plnkr.co/edit/OJfb9VDqlrRH4oHXQJyg?p=preview.
Note that you can't leverage of FormBuilder with ngControl since the latter allows you to define inline form. With FormBuilder you must use ngFormControl instead.
Here is a sample:
<div [ngClass]="{alert: !userForm.controls.name.valid}">
<label for="name">Name</label>
<input [ngFormControl]="userForm.controls.name"
id="name" [(ngModel)]="user.name"/>
</div>
See this article for more details:
http://restlet.com/blog/2016/02/11/implementing-angular2-forms-beyond-basics-part-1/

Dynamically adding form elements with jQuery and Zend_Form

I have a form in which people shall be able to add the same portion of elements with a plus-button, so that something like this is produced:
<div id="person-1" class="person">
<input type="text" name="name-1" id="name-1" />
<input type="text" name="age-1" id="age-1" />
</div>
<!-- as of here, it's JS created -->
<div id="person-2" class="person">
<input type="text" name="name-2" id="name-2" />
<input type="text" name="age-2" id="age-2" />
</div>
<div id="person-3" class="person">
<input type="text" name="name-3" id="name-3" />
<input type="text" name="age-3" id="age-3" />
</div>
I already managed to write jquery-code that allows me to add the same elements once again with a new id (name-1, age-1, name-2, age-2, name-3, age-3, …).
Of course, Zend_Form does not know about name-2 and name-3, so it just drops them when the form contains an error and is displayed again. Neither can I access the value of name-2 with $form->getValue('name-2'). I have to go over raw $this->getRequest()->getPost().
Is there a better method I can use to combine Zend_Form and javascript-based added form elements (of same type like an hardcoded element).
Caveat: In the real problem, it’s select and not input. Found out this could make a difference (with ->setIsArray(true)), but using select would blow up the example code.
What you could do is create a subform container inside your main form and add an X amount of subforms to that container.
For example:
class My_Form extends Zend_Form
{
private $_numPersons = 1;
public function setNumPersons($numPersons)
{
$this->_numPersons = (int) $numPersons;
}
public function init()
{
$container = new Zend_Form_SubForm();
$this->addSubForm($container, 'persons');
for($index = 0; $index < $this->_numPersons; $index++) {
$personForm = new My_PersonForm();
$container->addSubForm($personForm, $index+1);
}
}
}
When rendered, the input fields will have names like persons[1][name]. Note the $index+1, Zend_Form does not allow a form to be named '0'.
Ofcourse, you should only use this method if the amount of person subforms is limited.
Another strategy would be to override the isValid method and use a single My_PersonForm form to validate all the person data.
Sidenote; the above code will only work when you define the numPersons as part of the options set, when creating the form instance. E.g.;
$form = new My_Form(array('numPersons' => 10));

Submit the value of a <p> element when an html form is submitted

I have this code: <p class = "foo">Text</p>
And I also have a form: <form action = "XXX.php" method = post></form>
However, how can I get the value of the <p> when I submit it, as the <p> element can be changed.
So what I mean is to be able to post the value of the <p> when the user submits the form, and to be able to access it from that php file with: $_POST['foo'];
Thanks, I have tried to be as clear as possible.
You have to use Javascript for that
A jQuery function that will work
$("form").submit(function(){
var value = $("p").html();
// If foo already exists
if( $("[name=foo]").length > 0 )
{
$("[name=foo]").val(value);
}
else
{
var input = $("<input />", { name : "foo",
value : value ,
type : "hidden" });
$(this).append(input);
}
});
Use
<input type="hidden" value="something" name="something" id="something" />
and when you change inner html of <p> change the value of hidden input.
I think your best bet is to make it an input with readonly enabled, and style to to look like a <p>. It's better then trying to add it to the POST parameters with JavaScript.
Here's a quick example. I bet it could still be improved with a few extra CSS quirks, experiment a bit.
The easiest thing to do is set the value of a hidden form field when you change the contents of your <p>.
Alternatively, you can get its contents and post with JavaScript.
For text you need to use input field:
<input type="text"/>
Form fields should must have an id:
<input type="text" id="pewpew" class="foo"/>
I would go with:
<input type="text" id="pewpew" class="foo" value="default text goes here"/>
OR
Go with different workarounds, like setting form's hidden elements on the fly, etc.
You can create hidden field on the fly and set its value on form submit. Like this:
<form id="form" action="/somewhere" method="post">
<p>Some text</p>
<input type="submit" value="Submit"/>
</form>
<script type="text/javascript">
var form = document.getElementById('form');
form.onsubmit = function()
{
var p = this.getElementsByTagName('p')[0];
if (!document.getElementById('pval'))
{
var pinput = document.createElement('input');
pinput.setAttribute('type', 'hidden');
pinput.setAttribute('id', 'pval');
pinput.setAttribute('name', 'p');
this.appendChild(pinput);
}
document.getElementById('pval').value = p.innerHTML;
return true;
}
</script>
Works, i've tested.