I want to compare my values using my formcontrol than using ngModel, when values is entered in my input box , I want to display my cancel image, so I given userTextValue as true inside subscribe, my query now is how to reset the value when cancel is clicked . I want the input box to be empty , now cancel button is hidden but still values available, I am using pipe to filter values.
<input matInput class="form-control input" placeholder="Enter name or Id" id="user"
[formControl]="userControl"[matAutocomplete]="auto>
<img src="assets/icons/cancel.svg" *ngIf="userTextvalue" class="cancel-icon"
aria-label="Clear" (click)="clearUserValues()">
ts:
constructor() {
this.userControl.valueChanges.subscribe((user) => {
this.filterResult = user;
this.userTextvalue = true;
});
}
clearUserValues() {
this.filterResult = "";
this.userTextvalue = false;
}
pipe.ts
import { Pipe, PipeTransform } from '#angular/core';
#Pipe({
name: 'filterUser'
})
export class FilterUserPipe implements PipeTransform {
transform(items: any[], searchText: string): any[] {
if (searchText && searchText.length > 1) {
items = searchText ? this.filterUsers(items, searchText) : items.slice();
} else {
items = [];
}
return items;
}
filterUsers(items: any[], value: string): any[] {
const filterValue = value.toLowerCase();
return items.filter(item => item.name.toLowerCase().indexOf(filterValue) === 0);
}
}
First of All you have to get knowledge about what is difference between template driven and reactive form approach. When any change happens in formcontrol, it return new object of form (included its formcontrols) and that's what make it synchronous approach.
Let me wrap up this in short scenario.
When any change happens in formcontrol input or html tag
it could be tracked by subscribed it.
for example
// getting specific FormControl changed value.
// form: FormGroup
this.form.get('name of your formControl').subscribe(value => {// here (value) is changed value of that particular formControl. });
2nd Approach
For example you have formcontrol on any clickable input button or select input.
then you can emit an method on event click and on that method you can subscribe changed value and compare or save it to where you want.
sample code ::::
<mat-select formControlName="transferType">
<mat-option [value]="type" *ngFor="let type of transferTypes" (click)="onChanges()">{{type}}</mat-option>
</mat-select>
i am calling "onChanges()" method when i selects an option then i am subscribing this formControl and getting changed value and compare selected value by comparing operation.
same as you can get changed value and then set it to any boolean type variable then you can set any div with *ngIf="" statement in your html template/
if any confusion let me know.
Thanks..
angular7 #reactiveforms #formcontrol
As per your question i'm not completely sure why you want to use the filter since you have not shown the code. However, if you want to just reset your control, change this.filterResult = "" to this.userControl.setValue('') in clearUserValues() method.
Also, since you are subscribing to the valueChanges, it would be better if you do it in ngOnInit().
Check stackblitz here
Your TS code will be like this.
ngOnInit() {
this.onchanges();}
onchanges() {
this.form.get('userControl').valueChanges.subscribe( data => {
// here you can set your boolean value for condition to show cancel button
and push the value/or object which you take from input textbox in an your array for further comparison.
});}
clearUserValues() {
// here you will be set your boolean for hiding cancel button
and then you will be set empty state to your formControl input by doing like this.
this.form.get('userControl').patchValue(//here you will be pass empty string '' or what ever you want set it to.);}
Related
I've created a form to edit data in a table. Several fields of the form are drop down lists (mat-select) that are populated from other tables in a database. I'm populating the drop downs (mat-select) successfully, but I'm struggling to set the selected value to match the data from the row that the user is intending to edit.
I actually have one dialog working, but for some reason a more complex dialog (with 3 drop downs) is not working. I was originally only setting the ngModel, but I've added in the [comparewith] in hopes of resolving the problem or learning more. My compare method always receives a null value for the second parameter.
certificationEdit.dialog.html:
<div class="form">
<mat-form-field>
<mat-label>Connector - {{m_connectorid}}</mat-label>
<mat-select [(ngModel)]="m_connectorid" [value]="m_connectorid" [compareWith]="compareConnector" required>
<mat-option *ngFor="let item of connectorList" [value]="item.id"> {{item.connector}} ({{item.id}}) </mat-option>
</mat-select>
</mat-form-field>
</div>
certificationEdit.dialog.component.ts:
export class CertificationEditDialogComponent {
connectorList = [];
m_connectorid: string;
ngOnInit() {
this.databaseService.loadConnectorList().subscribe(response => {
this.connectorList = response as any[];
});
}
compareConnector(obj1: string, obj2: string) {
return obj1 === obj2;
}
constructor(
public dialogRef: MatDialogRef<CertificationEditDialogComponent>,
#Inject(MAT_DIALOG_DATA) public data: CERTIFICATION,
public databaseService: DatabaseService
) {
this.m_connectorid = this.data.connectorid;
}
The code opening the edit dialog:
public CertificationStartEdit(
i: number,
id: string,
releaseid: string,
productid: string,
connectorid: string,
certtype: string,
driverversion: string,
certdate: string,
changeneeded: string,
comments: string
) {
//this.release = release;
this.index = i;
const dialogRef = this.dialog.open(CertificationEditDialogComponent, {
data: {
id: id,
releaseid: releaseid,
productid: productid,
connectorid: connectorid,
certtype: certtype,
driverversion: driverversion,
certdate: certdate,
changeneeded: changeneeded,
comments: comments
}
});
The label shows m_connectorid has the value I expect, and the drop down list shows the id used for the value has the value I expect. None the less, the value I expect to be selected is not being selected.
You shouldn't bind to both ngModel and value - use one only, in your case ngModel because you are using template forms (if using reactive forms use formControl or formControlName instead).
Because of ngModel/forms, using MatSelect.value to determine what is selected might not work. I'm not sure if that's a bug or if it just isn't designed to work that way. Instead you should use MatSelect.selected.value (single selection) or just the bound variable m_connectorid or MatSelect.ngControl.value.
I have created a custom element in Aurelia.
import {bindable, inject, customElement, bindingMode} from 'aurelia-framework';
import 'select2';
import * as $ from 'jquery';
import {BindingSignaler} from "aurelia-templating-resources";
#customElement('select2')
#inject(Element, BindingSignaler)
export class Select2CustomMultiselect {
#bindable name = null; // name/id of custom select
#bindable selected = null; // default selected values
#bindable ({defaultBindingMode: bindingMode.oneWay, attribute:"options"}) source:Array<{id:number, name:any}>= []; // array of options with id/name properties
#bindable placeholder = "";
#bindable allow_clear = true;
private $select2: $;
constructor(private element, private signaler:BindingSignaler) {
}
attached() {
let $select = $(this.element).find('select');
this.$select2 = $select.select2({theme: 'bootstrap', placeholder: this.placeholder});
// on any change, propagate it to underlying select to trigger two-way bind
this.$select2.on('change', (event) => {
if (event.originalEvent) { return; }
const select2Value = this.$select2.val();
if(select2Value == this.selected) { return; }
// dispatch to raw select within the custom element
var notice = new Event('change', {bubbles: true});
event.target.dispatchEvent(notice);
});
this.$select2.val(this.selected);//.trigger('change');
}
selectedChanged(newValue,oldValue){
console.log(newValue);
}
detached() {
$(this.element).find('select').select2('destroy');
}
}
And it's template:
<template>
<select value.two-way="selected" name.one-way="name" id.one-way="name" class="form-control" data-allow-clear.one-way="allow_clear" size="1">
<option></option>
<option repeat.for="src of source" model.bind="src.id">${src.name & t}</option>
</select>
</template>
I use the control like this:
<select2 name="payingBy" selected.two-way="model.countryId & validate" options.bind="countries" placeholder="${'Select' & t}" allow_clear="true"></select2>
And model is:
countries:Array<{id:number, name:string}> = [{id:1, name:"USA"}, {id:2, name:Canada'}];
model.countryId: number;
Now, everything works fine if I change the select and on initial binding.
But if i change the model.countryId from ie. 1 to 2, the change is not reflected in the select control, the control still displays "USA" as like 1 is selected.
Because 'selected' property is bind two-way I would expect it to update the select when it change. But it does not. Why?
What Am I doing wrong?
Please help
Ok, I implemented it like in this post:Custom Select2 Aurelia component
And it works perfectly.
That is because you are using the data version which expects an object, but you have set your select to work with the id value only. So you should use the val to pass the id.
selectedChanged(newValue, oldValue) {
console.log(newValue);
if (this.select2) {
this.select2.select2({
val: newValue, // << changed this from data: newValue
theme: 'bootstrap',
placeholder: this.placeholder
});
}
I am trying to use Remote Validation with an additional bool checkbox field
[Remote("IsStorageConnectionValid", "TenantManagement", AdditionalFields = "CreateStorage")]
public String StorageConnectionString { get; set; }
Validation code
public JsonResult IsStorageConnectionValid(string storageConnectionString, bool createStorage){
It works perfectly in terms of it hitting the validator. However createStorage is always true irrespective of the value of the checkbox. If I use additional fields that aren't check boxes they are supplied perfectly.
Checkbox created as standard:
#Html.CheckBoxFor(m => m.CreateStorage)
Is this a bug? Or am I doing it wrong?
Fiddle Is here (Is MVC4 I think but does the same thing)
It does appear that this is a bug when used with #Html.CheckBoxFor. The problem is that CheckBoxFor renders 2 elements, a checkbox with value="true" and a hidden input with value="false" (Unchecked checkboxes do not post back so the second hidden input ensures a value is posted back for use by the DefaultModelBinder)
Looking at the relevant section of the jquery.validate.unobtrusive.js file
adapters.add("remote", ["url", "type", "additionalfields"], function (options) {
var value = {
url: options.params.url,
type: options.params.type || "GET",
data: {}
},
prefix = getModelPrefix(options.element.name);
$.each(splitAndTrim(options.params.additionalfields || options.element.name), function (i, fieldName) {
var paramName = appendModelPrefix(fieldName, prefix);
value.data[paramName] = function () {
return $(options.form).find(":input[name='" + escapeAttributeValue(paramName) + "']").val();
};
});
setValidationValues(options, "remote", value);
});
the return statement returns (in your case) .find(':input[name="CreateStorage"]').val(); which returns the value of the first input with the name="CreateStorage" which will always be true (the value of the checkbox)
As a test, if you render the value using HiddenFor rather that CheckBoxFor you will receive the correct value in your IsStorageConnectionValid method (but of course this does help since you cant change the value)
Not sure of the best solution, but the unobtrusive script should be first checking if .find(..) returns more than one element, then if the first is a checkbox which is unchecked, returning the value of the second element.
Edit
I have reported this as an issue at Codeplex
Edit 2
I have been advised the the issue has now been fixed here
How I can strip out the variables listed below from within a textbox (input) that if a user tries to type a URL i.e these variables:
"http://"
"www."
".com"
".co.uk"
If any of the variables above exist in the textbox on keyup the submit button gets disabled or/and it removes/strips out the variables above.
Is this possible? I've tried doing it using Charcodes, but I face the problem that I would like the user to still use '.; (full-stops) etc
Can somebody help?
Thanks,
Here you go!
Demo
$("#myinput").keyup(function()
{
var a = ["http://", "www.", ".com", ".co.uk"]; //Add the substrings
a.forEach(function(k)
{
if($("#myinput").attr("value").indexOf(k) > -1)
{
alert('Found!'); //Do something
return true;
}
else
{
return false;
}
});
});
Every time the user types a char, it checks for the string in array a. If the substring is found, it popups an alert message.
Using blur it will check for the string only when the user go outs of the input box (its more efficient using blur, but you can use this way if you want to check few strings and the input value is not too long).
Try this,
$("#textboxId").blur(function (event) {
var text = event.target.val();
if(text.contains("www")) {
$("submitBtnId").prop('disabled', true);
}
});
I am using the custom binding provided in How to create an auto-complete combobox?
I want to allow the user to either select a value from the list of suggestions or enter a value that is not in the list of suggestions. How can I get the value of the input into my observable field?
For example, if the user types 'smi' the autocomplete list will show Smith and other surnames beginning with 'smi', however, if they do not select an option from the list, I just want to set the value of my observable field to be 'smi'. At present, the only way the observable propety is set is when the user selects an item from the list of suggestions.
I have the following code (HTML):
<input type="text" data-bind="
value: surname,
jqAuto: { autoFocus: true },
jqAutoSource: surnames,
jqAutoQuery: surnameAutocomplete,
jqAutoValue: surname"
/>
JavaScript view model (simplified):
var vm = {
surnames: ko.observableArray(),
surname: ko.observable(),
surnameAutocomplete: function (searchTerm, result) {
repository.surnameAutocomplete(searchTerm, result);
};
Solution:
I amended the custom binding handler in two places:
init: function - added the following
// New setting to allow / disallow a user to enter values that are in the autocomplete list.
forceSelection = allBindings.jqAutoForceSelection;
options change function - amended to the following
//on a change, make sure that it is a valid value or clear out the model value
options.change = function (event, ui) {
var currentValue = $(element).val();
// Start: new code, check new setting on whether to force user to make a selection
if (!forceSelection) {
writeValueToModel(currentValue);
return;
}
// End: new code
var matchingItem = ko.utils.arrayFirst(unwrap(source), function (item) {
return unwrap(inputValueProp ? item[inputValueProp] : item) === currentValue;
});
if (!matchingItem) {
writeValueToModel(null);
}
}
I also found that the first item in the autocomplete list was being automatically selected, but then noticed by setting autofocus: false solved my issue, e.g.,
<input type="text" data-bind="
jqAuto: { autoFocus: false }, /* This fixes the auto select issue */
jqAutoSource: surnames,
jqAutoQuery: surnameAutocomplete,
jqAutoValue: surname,
jqAutoForceSelection: false"
/>
If you look closely at the binding handler you're using, you will notice this section:
//on a change, make sure that it is a valid value or clear out the model value
options.change = function(event, ui) {
var currentValue = $(element).val();
var matchingItem = ko.utils.arrayFirst(unwrap(source), function(item) {
return unwrap(item[inputValueProp]) === currentValue;
});
if (!matchingItem) {
writeValueToModel(null);
}
What this section of the binding handler essentially does is check if the text the user entered into the text field matches something in the autocomplete dropdown, and if it doesn't, it clears the model value (which it sounds like what you want to change).
You can either try deleting this section or extend it to suit your purposes.