ng select - multiple values - select same values more than once - html

is there a way to use ng select to have multiple selections and the possibility to have the same value/s more than once in the same selection?
I could only achieve multiple with each value possible to choose only once:
HTML code:
<ng-select [closeOnSelect]="false" [selectableGroup]="true" [items]="allowedValues"
[(ngModel)]="selectedValuesArray" [selectableGroupAsModel]="false"
(change)="raiseChangeEvent($event)" name="dropdown-element" [multiple]="true" [maxSelectedItems]="maxLength"
[clearable]="false">
<ng-template ng-option-tmp let-item="item">
<div class="option-line">
<p>{{item == null ? 'N/A' : item}}</p>
</div>
</ng-template>
</ng-select>

You could exploit the bindLabel and bindValue attributes.
suppose you pass in the following items:
allowedValues= [
{label: 1, value: 'first_0'},
{label: 2, value: 'second_0'}
]
Your HTML will look like this, mind the addition of bindLabel and bindValue, the change in (change) and the [hideSelected] attribute:
<ng-select [closeOnSelect]="false" [selectableGroup]="true" [items]="allowedValues"
[(ngModel)]="selectedValuesArray" [selectableGroupAsModel]="false"
(change)="raiseChangeEvent($event); addItem($event)" name="dropdown-element" [multiple]="true" [maxSelectedItems]="maxLength"
[clearable]="false" bindLabel="label" bindValue="value" [hideSelected]="true">
<ng-template ng-option-tmp let-item="item">
<div class="option-line">
<p>{{item == null ? 'N/A' : item}}</p>
</div>
</ng-template>
</ng-select>
Whenever an item is selected you could insert a new one in the list with the addItem() function. For example when the user selects 1, add {label: 1, value: 'first_1'} to the allowedValues. This way you will end up with an array of values that are unique, but the user is tricked into believing he is actually clicking the same items over and over again.

Related

Angular - Display different dropdown values based on condition

I am displaying data value as dropdown if below condition in html is met.
I would like to add another condition where on change of another dropdown which contains companies name I show data1value. For example if 1st dropdown (companies name) is changed toAmazonthen I only displaydata1` as its value
<dd>
<mat-select *ngIf="editMode"; else showData" [disabled]="!editMode"
[(ngModel)]="term.data" (ngModelChange)="recordModified.emit()">
<mat-option *ngFor="let tag of data" [value]="tag.value">{{tag.text}}</mat-option>
</mat-select>
<ng-template #showData>{{term.data}}</ng-template>
</dd>
data = [
{value: '1', text: 'Amazon'},
{value: '2', text: 'Google'},
{value: '3', text: 'Apple'},
data1 = [
{value: '1', text: 'Amazon'},
From what I can gather you want to access the data that has been selected by the dropdown, correct? You're close... check out this demo for a working version https://stackblitz.com/edit/angular-ivy-xmxqpg?file=src%2Fapp%2Fapp.component.ts

Show default value in drop down text box when there is single value in list

If the drop down has only one value, then I need to show that value as default value in drop down.
Eg: If "Fruits" drop down has only 1 value, then I need to show that value as default value
<div *ngIf='items.length>0'>
<span *ngIf= "isAllFruitsSelected; else Fruitname">{{'ALL'}}</span>
<ng-template #Fruitname>
{{this.form.value.selectedFruits.length}} + 'Fruit Selected'}}
</ng-template>
</div>
try this:
<ng-template #Fruitname>
{{ this.form.value.selectedFruits.length = 1 ? this.form.value.selectedFruits[0]?.name : (this.form.value.selectedFruits.length + 'Fruit Selected') }}
If selectedFruits is an array of fruit names (strings), you don't need the ?.name. (just this.form.value.selectedFruits[0]).
If it is an object array, you should change the attribute 'name' in *?.name for the suitable attribute for your objects.

Loop items with higher click_count first

I am making a recent search results component. In this component im taking search results from the API, and there is a value called "click_count". Every time someone get a positive result from the recent search that was clicked this value will increase by one.
Now I want to show the ones with the highest click_count first. Anyone knows how this is possible?
HTML
<ng-container *ngFor="let recent of searchSrvc.displayRecents | slice:0:5; let i=index">
<div class="result-row-wrapper">
<div class="icon-row-wrapper recents">
<ng-container>
<i class="fas fa-clock" (click)="setRecent(recent)"></i>
<p class="label" (click)="setRecent(recent)">{{ recent.search_text }}</p>
</ng-container>
<ng-container *ngIf="recent.user_id === this.model.id">
<i class="own-search fas fa-times" (click)="deleteSearch(i)"></i>
</ng-container>
</div>
</div>
</ng-container>
TS
The typescript just consists of an array im calling with multiple items that look like this:
{
archived: "0"
atime: null
auser: null
click_count: "0"
ctime: "1633514604"
cuser: "Dev Gebruiker"
id: "7"
mtime: "1633514604"
muser: "Dev Gebruiker"
organisation_id: "31"
resource: "building"
results_count: "0"
search_text: "add e"
ucurrency: "EUR"
user_id: "1"
},
Changing the order of items in an array is called sorting. The Array prototype already contains a method to sort, Array#sort.
const sortedArray = [...array].sort((a, b) => {
return Number(b.click_count) - Number(a.click_count)
})
Now use this sortedArray in your template with a regular *ngFor.

Ngx-datatable wrongly in (component) HTML how do I sort table by column name with a dropdown box (Angular 7)

I am needing to have a dropdown box that sits above a Ngx-datatable and that dropdown box needs to sort the Ngx-datatable by the values in the dropdown box. I am still new to Angular, so as I discovered that it is wrong to have the ngx-datatable in the component.html. How might I bootleg the datatable so that I can sort the rows by the values in the dropdown box?
Thinking that the method in the component.ts was linked to the datatable I was going to call that method in the dropdown box to sort it. It is completely separate!
component.html
<ngx-datatable class="expandable"
[rows]="rows"
[columns]="columns"
[headerHeight]="40"
[rowHeight]="'auto'"
[columnMode]="'force'" [limit]="20" [footerHeight]="50">
<ngx-datatable-column name="Header">
<ng-template let-value="value" let-row="row" ngx-datatable-cell-template>
<span class="custom-cell"><a (click)="method(content, id, false)">{{value}}</a></span>
</ng-template>
</ngx-datatable-column>
My dropdown box
<div ngbDropdown class="filter-dropdown-wrapper">
<button class="btn btn-light filter-button" id="input1" ngbDropdownToggle>Select an option</button>
<div ngbDropdownMenu aria-labelledby="inputmethod">
<!--<select (change)="getColumnNames($event.target.value)">
<option *ngFor="let element of rows" value="{{element.header}}"></option>
</select>-->
component.ts
columns = [
{ prop: 'header', name: 'Header' },
{ prop: 'notrelavant', name: 'Not Relevant' }, ];
What I need is: On click of the header value in dropdown box sort the datatable.
I have came up with a solution for yours. It is actually not very difficult if we break down the steps:
1) On the ngbDropdown, we populate the menu items with the columns of the datatable. we attach a click event binding on each individual menu items, and we bind them to the sort() method, which takes in the column property (column.prop) as a parameter.
<div ngbDropdown class="d-inline-block">
<button class="btn btn-light filter-button" id="input1" ngbDropdownToggle>Select an option</button>
<div ngbDropdownMenu aria-labelledby="inputmethod">
<button ngbDropdownItem *ngFor="let column of columns" (click)="sort(column.prop)">
{{ column.prop }}
</button>
</div>
</div>
2) Now, on our component.ts, we define our sort() method. rows represent the data in the datatable. We use localeCompare
to sort it in alphanumerical order. We create a shallow copy of rows to explicitly trigger change detection within the datatable to update the order of the data.
sort(prop) {
this.rows.sort((a, b) => a[prop].localeCompare(b[prop], 'en', { numeric: true }));
this.rows = [...this.rows];
}
I have created a working demo over here. Hope it helps in my explanation!

Display label displayed in options as the title of select

How to show option.Brand.Name as the title of the select field without using java script and changing the ng-model?
<select ng-model="detail.BrandId" title="" class="form-control" disabled>
<option ng-repeat="option in mainCtrl.products" ng-selected="option.Id === detail.ProductId" ng-value="option.BrandId">{{option.Brand.Name}}</option>
</select>
AngularJS and select-options
Try using ng-options AngularJS ngOptions directive within select element itself. Then you don't need to add each option element yourself using ng-repeat.
Clarification
The title-attribute belongs to the select-element and will show if you hover over the select. You would like the title to reveal the current selected option? Did I understand you correctly?
How to show option.Brand.Name as the title of the select field
Curious, where this detail.ProductId comes from? Is the brand preselected by product-id (see your code)?
ng-selected="option.Id === detail.ProductId"
Solution space
Your requirements/restrictions are:
without using JavaScript (maybe because you can't change the sources)
without changing the ng-model (because you need there only the BrandId for some database-reasons)
So since the title of the select-element has no access to the options inside, the only way to set it is depending on the current selection, i.e. your detail.BrandId. So the title can only set dynamically (depending on the current selection) by using standard-angularJS means, as:
{{ expression }} expressions
{{ expression | filter }} array-filter
Expected behavior
The only scope-variable changed by selecting is specified within select's ng-model as detail.BrandId. This will be set when user selects an option to its property BrandId. When user selects between options they will be visible with ther BrandName as label. After selection this BrandName (label of the option) should be shown as title of the entire select element.
So we need to get from detail.BrandId (selected ng-model) to related options BrandName (as this should show as title).
Possible Solution
Only way is to use standard angular expressions/filters/array-indexing to get the whole option by the selected detail.BrandId (ng-model)
Then we can lookup the option.BrandName by this equation after selected detail.BrandId === option.BrandId
var app = angular.module('app', []);
app.controller('mainCtrl', function($scope){
$scope.products = [
{Id: 0, name: 'Watson', brandId: 1, brandName:"IBM"},
{Id: 1, name: 'DB2', brandId: 1, brandName:"IBM"},
{Id: 2, name: 'Windows', brandId: 2, brandName: "Microsoft"},
{Id: 3, name: 'Office', brandId: 2, brandName: "Microsoft"}
];
$scope.detail = { ProductId: 3, BrandId: null };
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.7.5/angular.min.js"></script>
<!DOCTYPE html>
<html>
<body data-ng-app="app" data-ng-controller="mainCtrl">
<table border="1">
<tr>
<th>Product Id</th><th>Product Name</th><th>Choose Brand</th><th>Brand Id</th>
</tr>
<tr>
<td>{{detail.ProductId}}</td>
<td>{{ (products | filter: {Id: detail.ProductId})[0].name }}</td>
<td>
<select class="form-control"
ng-model="detail.BrandId"
ng-init="detail.BrandId = (products | filter: {Id: detail.ProductId})[0].brandId"
ng-options="o.brandId as ('['+ o.Id +'] '+ o.name +' : '+ o.brandName +' ('+ o.brandId +')') for o in products"
title="{{ (products | filter: {brandId: detail.BrandId})[0].brandName}}"
>
<!-- default option when not preset by detail.ProductId-->
<option value="">-- please choose brand --</option>
</select>
</td>
<td>{{detail.BrandId}}</td>
</tr>
</table>
<hr/>
<p>Product is predefined. So the brand is pre-selected by product. BUT: after brand is selected, the product-details do NOT change!</p>
Selected <strong>detail</strong>:
<pre ng-model="selected">{{detail | json}}</pre>
</body>
</html>
See also
For using ng-options, see also plunkr example.
You can register the selected option object in the ng-repeat parent scope by using as alias-expression provided by ng-repeat.
In your case you just need to do something like that:
<select ng-model="detail.BrandId"
title="{{options | selectedProductFilter : detail.ProductId}}"
class="form-control"
disabled>
<option ng-repeat="option in mainCtrl.products as options"
ng-selected="option.Id === detail.ProductId"
ng-value="option.BrandId">
{{option.Brand.Name}}
</option>
</select>
The options object will be available in your controller closure and you can display the title by using a custom filter.
angular.module("app").filter('selectedProductFilter',
function () {
return function (input, id) {
if (!input) return "";
let occurence = input.filter(function (x) {
return x.Id == id;
});
return occurence.length > 0 ? occurence[0].Brand.Name: "";
}
}
);
you need to do ng-change event in your select and call function in it that change the value of label text to the select value name. something like below
In Html
ng-change="changedValue(detail.BrandId)"
In JS
$scope.changedValue = function(item) {
//change label name here
}
fill ng-model by "option" not "option.BrandId"
then you can set title like this :
mainCtrl.products['ng-model-name'].Brand.Name
Here's how you could achive this:
(function () {
"use strict";
const app = angular.module("app", []);
app.controller("app.AppCtrl", $scope => {
$scope.selectedOption = null;
$scope.optionList = [{_id: 1, label: 'Option 1'}, {_id: 2, label: 'Option 2'}];
});
})();
body {
margin: 20px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.7.5/angular.min.js"></script>
<div ng-app="app" ng-controller="app.AppCtrl">
<select title="{{selectedOption.label}}" class="form-control" ng-model="selectedOption">
<option ng-repeat="option in optionList" ng-value="option"> {{option.label}}</option>
</select>
</div>
Try using ng-init,
add ng-init to your select tag and put your object index value you want to be selected by default.
e.g.
Your code
<select ng-model="detail.BrandId" title="" class="form-control" disabled>
<option ng-repeat="option in mainCtrl.products" ng-selected="option.Id === detail.ProductId" ng-value="option.BrandId">{{option.Brand.Name}}</option>
</select>
adding following code (Suppose I want index 0 by index):
ng-init="detail.BrandId = option[0].Brand.Name"
It will look like this :
<select ng-model="detail.BrandId" ng-init="detail.BrandId = option[0].Brand.Name" title="" class="form-control" disabled>
<option ng-repeat="option in mainCtrl.products" ng-selected="option.Id === detail.ProductId" ng-value="option.BrandId">{{option.Brand.Name}}</option>
</select>
or Check these thread's
how to use ng-option to set default value of select element
How to set default value in ng-options