Here is my emp array of object:
emp[
{"id":1001,"name":"robin_delhi"},
{"id":1002,"name":"robin_mumbai"},
{"id":1003,"name":"robin_bang"},
{"id":1004,"name":"sushil_delhi"},
{"id":1005,"name":"sushil_mumbai"},
]
Here is my HTML template, I am displaying emp object in drop down through mat select component of angular material:
<mat-form-field>
<mat-select [(ngModel)]="emp" [(value)]="sel" placeholder="Employee
[formControl]="toppings" multiple required>
<mat-option *ngFor="let p of emp | proDisable:emp:sel; let p = index;" [value]="p">
{{p.name}}
</mat-option>
</mat-select>
</mat-form-field>
I want when particular emp name will selected, it will match with remaining element (first part of special character “_”), if match found it will show as usual else disabled.
Here is my custom pipe:
import { Pipe, PipeTransform } from '#angular/core';
#Pipe({
name: 'proDisable'
})
export class ProDisablePipe implements PipeTransform {
transform(value:any, data:any, sel:any) : any {
if(!sel)
{
return value;
}
else
{
let nval:any;
for(var i=0; i<data.length; i++)
{
for(var j=0; j<sel.length; j++)
{
if ((i['name'].substring(0, i['name'].indexOf("_")))==(sel['name'].substring(0, sel['name'].indexOf("_"))))
{
nval= "class='disable'"+value;
}
else
{
nval= "class='enable'"+value;
}
}
}
return nval;
}
}
}
Here if I select first element, the last two will be disabled.
Kindly help how to achieve this or any better way to do this.
Related
I have a email subject textbox where I can input combination of dynamic dropdown value and other text entered by user, here I can enter only one dynamic value at start, cant add another dynamic value after that please help.
its an email subject for example there are 3 dynamic value here ["creditcard","accountno","Amount"].
sample output - "Hi jack your creditcard with accoutno has due Amount" here creditcard accoutno and Amount are dynamic value from dropdown and rest are normal text
HTML
<div class="textbox">
<label class="textbox__label" [for]="id">{{label}}</label>
<input class="textbox__input" [type]="type" [id]="id" [placeholder]="placeholder" [value]="value" [name]="name"
autocomplete="off" (input)="onChange($event)" (keyup.Space)="doSomething()" [(ngModel)]="model" />
<ul class="textbox__dropdown" *ngIf="show">
<ng-container *ngFor="let list of listData ; let i = index">
<li (click)="handleSetValue(list)">
<span [style.background-color]="colors[i % colors.length]">{{list.value.charAt(0)}}</span>
{{list.value}}
</li>
</ng-container>
</ul>
</div>
TS
import { Component, VERSION,Output, EventEmitter } from '#angular/core';
import { isEmpty } from 'lodash';
#Component({
selector: 'my-app',
templateUrl: './app.component.html',
styleUrls: [ './app.component.css' ]
})
export class AppComponent {
name = 'Angular ' + VERSION.major;
public dynamicList = ["creditcard","accountno","Amount"]
public value;
public listData: any;
public show: boolean = true;
public model: any;
#Output() selectedValue = new EventEmitter();
onChange(event: any) {
if (event.target.value !== '' && this.dynamicList) {
console.log(event.target.value);
this.show = true;
const item = this.dynamicList.filter((items) => items.toLowerCase().includes(event.target.value));
if (!isEmpty(item)) {
this.listData = item;
console.log(item)
} else {
this.show = false;
this.selectedValue.emit(event.target.value)
}
} else {
this.listData = this.dynamicList;
this.show = false
}
}
Stackblitz-link
You can split the event.target.value that you are making in onChange() method like,
const getLastSearch = event.target.value.split(' ');
Then in the filter method you can use the last recent search into includes to check and display the latest search result like,
const item = this.dynamicList.filter((items) => items.toLowerCase().includes(getLastSearch[getLastSearch.length - 1]));
In app.component.html , for the input box you could use space bar event and call a method to show the dropdown items like,
<input class="textbox__input" type="type" id="id" name="name"
autocomplete="off" (input)="onChange($event)" (keyup.Space)= "spaceEvent($event)" [(ngModel)]="model" />
And the spaceEvent() as follows,
spaceEvent(event: any){
this.listData = this.dynamicList;
this.show = true;
}
Then finally you could split the strings available in the text box and then you can join it by removing the last one and append the clicked list item to as the last item like,
handleSetValue(list) {
let splittedSearch = this.model.split(' '); // Split each string with space
splittedSearch[splittedSearch.length - 1] = ''; // Make the last string empty
splittedSearch = splittedSearch.join(' ') // Join all the splitted string with space
splittedSearch += list; // Concat the splitted search with the selected list item
this.model = splittedSearch; // Assign the splittedsearch to model
this.show = false;
}
Forked Stackblitz here...
Please make the changes as per this
. In TS file
public model: any = "";
onChange(event: any) {
var value = event.target.value;
var inputarray = value.split(" ");
var lastinput = inputarray[inputarray.length - 1]
console.log(lastinput)
if ((value !== '' || inputarray.length> 1) && this.dynamicList) {
console.log(value);
this.show = true;
const item = this.dynamicList.filter((items) => items.toLowerCase().includes(lastinput));
if (!isEmpty(item)) {
this.listData = item;
console.log(item)
} else {
this.show = false;
this.selectedValue.emit(value)
}
} else {
this.listData = this.dynamicList;
this.show = false
}
}
handleSetValue(list) {
debugger
if(this.dynamicList.find(s=>s == list)){
this.model += " "+list;
}
this.show = false;
// this.selectedValue.emit(list.key)
}
in HTML
<div class="textbox">
<input class="textbox__input" type="type" id="id" name="name"
[ngModel]="model" autocomplete="off" (input)="onChange($event)"/>
<ul class="textbox__dropdown" *ngIf="show">
<ng-container *ngFor="let list of listData">
<li (click)="handleSetValue(list)">
{{list}}
</li>
</ng-container>
</ul>
</div>
I am working on making custom multi select using text box.if user enter 1,2,3,4 then 1 2 3 4 should be considered as separate value.i am bale to make this using <input type="text"> but instead of text box i want to div so user can click anywhere in the div and able to add item.
following image is my current implementation.
custom-autocomplete.component.html
<div name="test">
<ul class="autocomplete-text base-auto-select-cointainer">
<li class="d-inline-flex selected-item" *ngFor="let item of itemList;let i=index" title="{{item}}">{{item}}
<span class="remove-item pointer" role="presentation" (click)="handelOnItemRemove(i)">×</span></li>
<li class="d-inline-flex">
<input class="item-input" type="text" (keyup)="handelOnItemKeyUp($event)"
tabindex="0" autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false"
role="textbox">
</li>
</ul>
</div>
custom-autocomplete.component.ts
import { Component, OnInit, Output, EventEmitter } from '#angular/core';
#Component({
selector: 'app-custom-autocomplete',
templateUrl: './custom-autocomplete.component.html',
styleUrls: ['./custom-autocomplete.component.css']
})
export class CustomAutocompleteComponent implements OnInit {
itemList: any[] = []; // for collection selcted items
userInputs: any;
model = 'some text';
constructor() { }
// event emiters for passing data to parent componet.
#Output() handelItemSelection: EventEmitter<any> = new EventEmitter<any>();
ngOnInit() {
}
handelOnItemKeyUp(event) {
if (event.target.value) {
let userInput: string = event.target.value;
let splitChar = userInput.charAt(userInput.length - 1);
let tempArray: any[] = userInput.split(',');
if (tempArray.length > 1) {
if (tempArray[0] != "" && tempArray[0] != undefined) {
this.itemList.push(tempArray[0])
this.handelItemSelection.emit(this.itemList); //passing updated items to parent
}
}
console.log('')
splitChar == ',' ?event.target.value = null : '' // setting empty value to text box when user enter ,
}
}
// code block for handel item removal from list.
handelOnItemRemove(index: number) {
this.itemList.splice(index, 1);
this.handelItemSelection.emit(this.itemList); //passing updated items to parent
}
}
can someone suggest me to how to implement this using <div contenteditable="true"></div>
I have written a directive for text input, to support int values.
Here is it
import { NgControl } from '#angular/forms';
import { HostListener, Directive } from '#angular/core';
#Directive({
exportAs: 'number-directive',
selector: 'number-directive, [number-directive]'
})
export class NumberDirective {
private el: NgControl;
constructor(ngControl: NgControl) {
this.el = ngControl;
}
// Listen for the input event to also handle copy and paste.
#HostListener('input', ['$event.target.value'])
onInput(value: string) {
// Use NgControl patchValue to prevent the issue on validation
this.el.control.patchValue(value.replace(/[^0-9]/g, ''));
}
}
And HTML
<div class="form-group">
<label>{{ l("RoomWidth") }}</label>
<input
decimal-number-directive
#roomWidthInput="ngModel"
class="form-control nospinner-input"
type="text"
name="roomWidth"
[(ngModel)]="room.roomWidth"
maxlength="32"
/>
</div>
But I need it to support decimal values. For example 99.5
How do I need to modify it?
Try this:
#HostListener('input', ['$event.target.value'])
onInput(value: string) {
// Use NgControl patchValue to prevent the issue on validation
this.el.control.patchValue(value.replace(/[^0-9].[^0-9]/g, ''));
}
Working_Demo
In my case I have need to considerate two consegutive point too and replace caracter. Maybe is writable with regex but this work for me.
Example if you type or paste 45.456.6 it will be repaced with 45.4566
#HostListener('input', ['$event']) onInputChange(event) {
let initalValue: string = this.el.nativeElement.value;
initalValue = initalValue.replace(/[^\.|0-9]/g, '');
// elimina le seconde occorrenze del punto
const count = (initalValue.match(/\./g) || []).length;
for (let i = 1; i < count; i++) {
initalValue = this.repaceSecondDotOccurrence(initalValue);
}
this.el.nativeElement.value = initalValue;
}
repaceSecondDotOccurrence(inputString): string {
let t = 0;
return inputString.replace(/\./g, function (match) {
t++;
return (t === 2) ? '' : match;
});
}
I have two radio buttons (they're not dynamically generated):
<input type="radio" name="orderbydescending" [(ngModel)]="orderbydescending" [value]="['+recordStartDate']">Ascending<br>
<input type="radio" name="orderbydescending" [(ngModel)]="orderbydescending" [value]="['-recordStartDate']">Descending
How do I make one of the radio buttons checked by default?
Thank you!
Edit
The button's values are being passed through this pipe (i.e. not a component, per se...not sure this is worth mentioning?). The app is pretty simple, and the radio buttons are just hardcoded into app.component. Is the pipe the correct place to initialize which radio button is checked by default?
import { Pipe, PipeTransform } from '#angular/core';
#Pipe({name: 'orderBy', pure: false})
export class OrderByPipe implements PipeTransform {
static _OrderByPipeComparator(a:any, b:any):number{
if((isNaN(parseFloat(a)) || !isFinite(a)) || (isNaN(parseFloat(b)) || !isFinite(b))){
//Isn't a number so lowercase the string to properly compare
if(a.toLowerCase() < b.toLowerCase()) return -1;
if(a.toLowerCase() > b.toLowerCase()) return 1;
}
else{
//Parse strings as numbers to compare properly
if(parseFloat(a) < parseFloat(b)) return -1;
if(parseFloat(a) > parseFloat(b)) return 1;
}
return 0; //equal each other
}
transform(input:any, [config = '+']): any{
if(!Array.isArray(input)) return input;
if(!Array.isArray(config) || (Array.isArray(config) && config.length == 1)){
var propertyToCheck:string = !Array.isArray(config) ? config : config[0];
var desc = propertyToCheck.substr(0, 1) == '-';
//Basic array
if(!propertyToCheck || propertyToCheck == '-' || propertyToCheck == '+'){
return !desc ? input.sort() : input.sort().reverse();
}
else {
var property:string = propertyToCheck.substr(0, 1) == '+' || propertyToCheck.substr(0, 1) == '-'
? propertyToCheck.substr(1)
: propertyToCheck;
return input.sort(function(a:any,b:any){
return !desc
? OrderByPipe._OrderByPipeComparator(a[property], b[property])
: -OrderByPipe._OrderByPipeComparator(a[property], b[property]);
});
}
}
else {
//Loop over property of the array in order and sort
return input.sort(function(a:any,b:any){
for(var i:number = 0; i < config.length; i++){
var desc = config[i].substr(0, 1) == '-';
var property = config[i].substr(0, 1) == '+' || config[i].substr(0, 1) == '-'
? config[i].substr(1)
: config[i];
var comparison = !desc
? OrderByPipe._OrderByPipeComparator(a[property], b[property])
: -OrderByPipe._OrderByPipeComparator(a[property], b[property]);
//Don't return 0 yet in case of needing to sort by next property
if(comparison != 0) return comparison;
}
return 0; //equal each other
});
}
}
Edit 2
So in component.app.ts I've edited my export class AppComponent{ to the following:
export class AppComponent {
artists = ARTISTS;
currentArtist: Artist;
orderbydescending = ['-recordStartDate'];
showArtist(item) {
this.currentArtist = item;
}
}
This works in terms of preventing the previous errors, but it doesn't actually make the radio button selected. It still appears as though it's unselected - even though it functions as though it is. Does this make sense?
If you're doing this in Angular 2+ with 2 way binding, in the component where this HTML is being used, you could just try initializing the value associated with the input.
// in your component ts file
orderbydescending: boolean = true;
and you could leave the HTML the same. Although, you seem to have 2 radio buttons associated with the same data value, orderbydescending. I don't know if that's what you intend, but it looks like it could cause problems.
Here's some code from my personal side project to give you a better idea.
#Component({
selector: 'gmu-home-page',
templateUrl: './home-page.component.html',
styleUrls: ['./home-page.component.css']
})
export class HomePageComponent implements OnInit {
// here you would put your variables
myFlag: boolean = true;
constructor() { }
ngOnInit() {
}
}
If orderbydescending and recordStartDate are members of your component class:
#Component({
...
})
export class MyComponent {
public recordStartDate: any = ...
public orderbydescending: any = +recordStartDate;
...
}
the appropriate radio button will be checked if you assign the radio button values with [value]:
<input type="radio" name="order" [(ngModel)]="orderbydescending" [value]="+recordStartDate">Ascending<br>
<input type="radio" name="order" [(ngModel)]="orderbydescending" [value]="-recordStartDate">Descending
In the case shown above, the ascending order radio button will be checked by default because the orderbydescending variable is initially set to +recordStartDate.
Note: The variables in my sample code are of type any because I don't know exactly what kind of data you are using. Your data will probably have a more specific data type.
Try this in the component
radioValue = {valueAsc: 'Asc', valueDesc: 'Desc'} ;
orderbydescending = 'Asc';
and in the template put this
<input type="radio" name="radioGroup" [(ngModel)]="orderbydescending" [value]="radioValue.valueAsc">Ascending
<input type="radio" name="radioGroup" [(ngModel)]="orderbydescending" [value]="radioValue.valueDesc">Descending
With this the first radio button is checked, if you don't want any radio button selected assign to the variable orderbydescending null.
orderbydescending = 'null;
So, my problem is that I want to create an search input field, which I have already done and I am using a search filter in an ng-repeat. What I want now to do is to select all the items I searched for using the select all checkbox.In this moment when I click the select all checkbox it checks all of my items from my array not from what I searched.
This is my html:
<div class="modal-body">
<div>
<md-input-container flex> <label>Search</label>
<input ng-model="search.name"> </md-input-container>
<md-button class="md-primary" ng-click="saveValues()">Update</md-button>
</div>
<div class="md-list">
<md-checkbox ng-model="modelItemsList.allItemsSelected"
ng-change="selectAll()">
Select all
</md-checkbox>
<md-list> <md-list-item class="md-3-line"
ng-repeat="mod
elItem in modelItemsList | filter:search">
<div class="md-list-item-text">
<md-checkbox ng-model="modelItem.isChecked " aria-label="Checkbox 1" ng-change="selectModelItem(modelItem)">
<h3>{{ $eval('modelItem.'+propertyName) }}</h3>
<p>{{ $eval('modelItem.'+propertyDesc) }}</p>
</md-checkbox>
</div>
</md-list-item> </md-list>
</div>
</div>
This is my select all function:
$scope.selectAll = function(){
console.debug("searchText", $scope.search);
//filteredArray = filterFilter($rootScope.modelItemsList, $scope.search);
//console.log(filteredArray);
console.log($rootScope.modelItemsList.allItemsSelected);
$rootScope.temp = [];
console.log($scope.modelItemsList);
$rootScope.modelItemsList.allItemsSelected = !$rootScope.modelItemsList.allItemsSelected;
console.log($rootScope.modelItemsList.allItemsSelected);
if($rootScope.modelItemsList.allItemsSelected){
for (var i = 0; i < $scope.modelItemsList.length; i++) {
$rootScope.temp.push($scope.modelItemsList[i].name);
console.log($scope.modelItemsList[i].name);
$scope.modelItemsList[i].isChecked = $rootScope.modelItemsList.allItemsSelected;
console.log($scope.modelItemsList[i].isChecked);
console.log($rootScope.modelItemsList.allItemsSelected);
}
}
else if (!$rootScope.modelItemsList.allItemsSelected){
for (var i = 0; i < $scope.modelItemsList.length; i++) {
$scope.modelItemsList[i].isChecked = $rootScope.modelItemsList.allItemsSelected;
$rootScope.temp = [];
console.log($scope.modelItemsList[i].isChecked);
}
}
}
I think I should make some kind of filter, but I am not so sure. I mean in my JS file in the select all function. Does anybody have any idea how should I do this ?
The easiest way to do this is to name the filtered list:
ie
<md-list-item class="md-3-line" ng-repeat="modelItem in filtered = ( modelItemsList | filter:search )">
...
</md-list-item>
Then in the controller you can access $scope.filtered
FYI
you can change {{ $eval('modelItem.'+propertyDesc) }} to
{{ modelItem[propertyDesc] }}
I'm sorry, but you weren't very clear in your question. From what I understand, this is what you want.
What I want now to do is to select all the items I searched for using the select all checkbox
Check out this plunkr where it's implemented.
https://plnkr.co/edit/vjzJEm8Wck8b5iUD4qz8?p=preview
The way you could do this is by setting up ng-change on your select all checkbox
<input type="checkbox" ng-change="selectAllFiltered()" ng-model="checkbox.value2" ng-true-value="true" ng-false-value="false"/>
Next, you would define the selectAllFiltered method in your controller. The objective is to set isSelected on $scope.filtered array when the array is filtered.
And when the array is NOT filtered, i.e. there is no string in the search.name field, then set isSelected on $scope.modelItemsList array.
Here's what your controller method should look like...
$scope.selectAllFiltered = function() {
if ($scope.checkbox.selectAll) {
$scope.checkbox.selectAll = false;
} else {
$scope.checkbox.selectAll = true;
}
if (!$scope.search.name) {
console.log('when no name is entered')
for (var i = 0; i < $scope.modelItemsList.length; i++) {
if (angular.isUndefined($scope.modelItemsList[i].isSelected)) {
$scope.modelItemsList[i].isSelected = $scope.checkbox.selectAll;
} else {
$scope.modelItemsList[i].isSelected = !$scope.modelItemsList[i].isSelected;
}
}
} else {
console.log('when some name is entered');
for (var i = 0; i < $scope.filtered.length; i++) {
if (angular.isUndefined($scope.filtered[i].isSelected)) {
$scope.filtered[i].isSelected = $scope.checkbox.selectAll;
} else {
$scope.filtered[i].isSelected = !$scope.filtered[i].isSelected;
}
}
}
}