AngularJS isteven-multi-select limit display options - javascript

I am using the isteven-multi-select to display select options from DB. Unfortunatelly it could be really large array (from "a few" to "+100K" records). That is the reason why I use a smart select with a filter. Is there any way how can I set limit of rendering options to improve performance? Currently the large array drop down a js and a firefox.
My select:
<div isteven-multi-select
input-model="data.select.options"
output-model="data.select.data"
button-label="label"
item-label="id label"
tick-property="ticked"
max-labels="4" >
</div>
Controller:
...
DataInfoResource.query(
function(data) {
$scope.data.select.options = data;
console.log(data);
}
);
....
I also tried select2 but I do not find any way how to do it.
Thanks for any advice.

This is what I did when the list size is more. Not sure if it would work for 100k records but still you can try. It really worked well for 6k record.
Modified the template in isteven-multi-select.js as follows
'ng-repeat="item in filteredModel | filter:removeGroupEndMarker" class="multiSelectItem"'
to
'ng-repeat="item in filteredModel | filter:removeGroupEndMarker | limitTo:100" class="multiSelectItem"'

May be try this one:
<div isteven-multi-select ... max-height="250px"></div>
PS. I can't add a comment because the following answer

Related

filtering in an ng-repeat from JSON response

I've got a question about filtering within a ng-repeat. But this isn't a simple question since I'm not really having a problem that needs a solution. In this case, i'm looking for the best possible answer that doesn't require a lot of code but still does the trick as to how I want it to. It will become more clear in my description.
a short introduction:
So I'm currently working on a shopping application. The shopping application has a connection with an existing PrestaShop webshop through the web service API. A rest API for PrestaShop. So after creating a customer section, products section, and a cart system, i would like to be able to update the "stock amount" of each product within the application. Many people would tell me: Well that's easy, just create a form with ng-repeat response data from the database and the possibility of updating the stock on let's say a button ng-click event.
Well I've done that but now the tricky part, and to explain I will provide some less important examples to make it more clear of what I'm asking:
The prestashop database
The prestashop database is a database that exists of over 250 tables. Among those tables are various connections through id's and attribute id's. Some simple examples are:
The customer table has an id_address row which connects to the address table. Within this table, all the 'customersaddress info is placed. So far, let's say updating a customer I've created a combination of update thecustomertable with thecustomer_idbut also update theaddresstable where theaddress_idis equal to theid_addressfrom the selectedcustomerwithin thecustomer` table.
Products also have some linked tables. Think about prices, taxes, sizes, and colors. The id_product_attribute is an attribute_id that could correspond to a color or size.
As explained above the prestashop database structure is very detailed wich confines to using various filters for showing the wanted data.
Using the webservice
So for using the webservice i'm using a combination of angularJS, javascript, php, and JSON. The JSON is the actual data. by using $http.get(url, options) i'm able to get the data from the database. Then for showing the data i'm using response. A example is shown below:
$http.get('config/get/getCustomers.php', { cache: true }).then(function (response) {
$scope.customers = response.data.customers.customer
});
using $scope.customers = response.data.customers.customer gives me the option to show the customer data by using, for example, a ng-repeat as in the example below
$http.get('config/get/getCustomers.php', { cache: true }).then(function (response) {
$scope.customers = response.data.customers.customer
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div class="row listrow" ng-repeat="customer in customers | orderBy: customer.id">
<div class="col-lg-8">
<p class="customer" ng-bind="customer.id + ' ' + customer.firstname + ' ' + customer.lastname">
</p>
</div>
</div>
In this case, the response would be empty since there is no database connection. To create a full example for testing here is some JSON data you could use from the customers table.
{"customers":{"customer":[{"id":"1","id_default_group":"0","id_lang":"0","newsletter_date_add":"0000-00-00 00:00:00","ip_registration_newsletter":{},"last_passwd_gen":"2017-10-30 09:27:03","secure_key":{},"deleted":"0","passwd":"$2y$10$eZvPTD9bkxwSfWN7qovrmee\/Den2TqZ5a6YjcGC\/lha3oU59MCjOO","lastname":"TestStefans","firstname":"John","email":"pub#prestashop.com","id_gender":"0","birthday":"0000-00-00","newsletter":"0","optin":"0","website":{},"company":{},"siret":{},"ape":{},"outstanding_allow_amount":"0.000000","show_public_prices":"0","id_risk":"0","max_payment_days":"0","active":"1","note":{},"is_guest":"0","id_shop":"1","id_shop_group":"1","date_add":"2017-04-26 14:01:31","date_upd":"2017-10-27 15:56:54","reset_password_token":{},"reset_password_validity":"0000-00-00 00:00:00","associations":{"groups":{"#attributes":{"nodeType":"group","api":"groups"},"group":{"id":"3"}}}},{"id":"2","id_default_group":"0","id_lang":"1","newsletter_date_add":"0000-00-00 00:00:00","ip_registration_newsletter":{},"last_passwd_gen":"2017-10-27 15:56:55","secure_key":{},"deleted":"0","passwd":"$2y$10$C8M6TIuzmZjP9kh06Hai8.XyuNG9WcSi9L34oXqAuidsJkoYog4WW","lastname":"Demoers","firstname":"Demoers","email":"demo#sdwebdesign.nl","id_gender":"0","birthday":"0000-00-00","newsletter":"0","optin":"0","website":{},"company":{},"siret":{},"ape":{},"outstanding_allow_amount":"0.000000","show_public_prices":"0","id_risk":"0","max_payment_days":"0","active":"1","note":{},"is_guest":"0","id_shop":"1","id_shop_group":"1","date_add":"2017-04-26 14:01:33","date_upd":"2017-10-27 15:56:55","reset_password_token":{},"reset_password_validity":"0000-00-00 00:00:00","associations":{"groups":{"#attributes":{"nodeType":"group","api":"groups"},"group":{"id":"3"}}}}]}}
So with this information here is my question:
While working on the application the following data is given within the stock_availables table.
So while using the $http.get() and the response functions I was able to create a form for updating the stock. But now take a look at the id_product_attribute. This row corresponds to a product_attribute. In this case a size or color. Now I would like to filter these results. In this case by using for example ng-if="id_product_attribute == 0" i'm able to filter in a way that only all with this id_attribute are shown. But I would like to show all of them. So also with id="1", id="2", etc. But there is where I'm wondering, is there a way to do this in a sufficient way that wouldn't require a ng-if for each id? Since there are around 50 different id_attribute's which each corresponds to a color or size. So is there a function that could get each different id and filter that in a sufficient way than using many ng-if clauses. Look at the following full code as an example.
myApp.controller('ProductsController', function($scope, $http){
$http.get('config/get/getProducts.php', {cache: true}).then(function(response){
$scope.products = response.data.products.product
});
// Stock check + view
$http.get('config/get/getStock.php', {cache: true}).then(function (response) {
$scope.stock_availables = response.data.stock_availables.stock_available
});
// Update Stock
$scope.updateStock = function(stock_available) {
var stock_id = stock_available.id;
var product_id = stock_available.id_product;
var stock_quantity = stock_available.quantity;
console.log(stock_id + product_id + stock_quantity);
// Post to the database //
};
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div class="row listrow">
<div class="col-lg-12 col-md-12 col-sm-12 col-xs-12">
<ng-form name="stock">
<div ng-repeat="stock_available in stock_availables">
<div class="row full-width padding-tb-15" ng-if="stock_available.id_product == product.id && stock_available.id_product_attribute == 0" ng-repeat="product in products">
<div class="col-lg-12 form-stock-group hidden">
<input title="id" type="text" name="stockId" class="form-control" aria-describedby="" ng-value="stock_available.id">
</div>
<div class="col-lg-4">
<h5 ng-bind="product.name.language"></h5>
</div>
<div class="col-lg-3">
<h5 ng-bind="product.ean13"></h5>
</div>
<div class="col-lg-2">
<h5 ng-bind="product.reference"></h5>
</div>
<div ng-if="stock_available.id_product == product.id && stock_available.id_product_attribute == 0" ng-repeat="stock_available in stock_availables" class="col-lg-1 text-center">
<input title="stock_id" type="text" name="stock_id" class="form-control hidden" aria-describedby="" ng-model="stock_available.id" ng-value="stock_available.id">
<input title="stock_id_product" type="text" name="stock_id_product" class="form-control hidden" aria-describedby="" ng-model="stock_available.id_product" ng-value="stock_available.id_product">
<h5 title="quantity" name="stockQuantity" aria-describedby="" ng-model="stock_available.quantity" ng-bind="stock_available.quantity"></h5>
</div>
<div ng-if="stock_available.id_product == product.id && stock_available.id_product_attribute == 0" ng-repeat="stock_available in stock_availables" class="col-lg-1 text-center">
<input title="updateStockAmount" class="form-control form-control-stock" type="number">
</div>
<div class="col-lg-1 text-center">
<a ng-click="printStockLabel()">
<i class="fa fa-print" aria-hidden="true"></i>
</a>
</div>
</div>
</div>
</ng-form>
</div>
</div>
I trying to create the following view:
Product-id 1: then all sizes, color's, etc
Product-id 2: then all sizes, color's, etc.
Yes it is possible with writing 50 different ng-if statements but i'm asking if there is a better, easier and more sufficient way to do this?
A simple build of the dummy code can be found here
As always,
Thanks in advance!
Have you considered using the database and letting the DB generate a specific query for this screen, which groups all the products together in a single row?.
so you currently have a bunch of "repeated" product IDs (since the query returns detailed information for color and size), but need to operate on the single record.
You can do that in the backend using a GROUP BY SQL query statement.
If the endpoint is being used by more programs, simply make your endpoint to be "only for this screen" and apply the necessary changes.
If changing the SQL on the backend is too complex (or politically inviable), you can always group_by using javascript:
https://www.consolelog.io/group-by-in-javascript
group_by takes as input a dataset and a column (i.e.).
given a dataset like:
c1 c2 c3
1 10 10
1 11 10
3 12 20
// this operation:
groups = group_by(dataset, "c1")
//returns this:
groups:
group 1 (2 elements)
c2 c3
10 10
11 10
group 3 (1 element)
c2 c3
12 10
this means you could feed the grouped dataset back into the grid program, so it can show groups as groups and items as items, by iterating first over the groups and later over the items.
There are many ways to implement group_by, like these:
What is the most efficient method to groupby on a javascript array of objects?
HTH
Maybe you should ask yourself what part of your application have the responsibility of sorting those attributes. This could lead to a more obvious solution for you.
If the responsibility goes to the API, then either your request or your API should return a ready-to-use JSON for your WebApp.
If the responsibility goes to the front WebApp, either do it in the js code or in the template.
My guess is that your API should do that, in which case i may not be the most advisor.
But if you decide to do this in the WebApp, I definitely think that you should not use ngIf to do that, but instead build Pure Functions in your JS to build one or several array that you will be able to use with not too much of functionnaly code in your template.
For example you could .map() your response and return a well iterable object, and/or chained it with a .concat() or whatever. If you need ideas to build such functions check those example http://reactivex.io/learnrx/
By reading your question, I would suggest instead of having the ng-if n times, you can have the logic for filtering inside your controller like
$scope.getFilteredList = function() {
return $scope.stock_availables.filter(function(stock) {
return stock.id_product === $scope.selectedID; // $scope.selectedID will be the id to be filter, in your example '0'
});
}
And your ng-repeat will be changed as
<div ng-repeat="stock_available in getFilteredList">
I think it's better for you to let DB order it for you.
But you can try AngularJS orderBy or filter
var module = angular.module('MyApp', []);
module.controller('MyController', function($scope){
$scope.list = [
{ 'id': 0, 'count': 10 },
{ 'id': 1, 'count': 9 },
{ 'id': 2, 'count': 8 }];
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="MyApp">
<div ng-controller="MyController">
<div ng-repeat="member in list | orderBy:'-count'">
{{member.id}}
</div>
<hr>
<div ng-repeat="member in list | filter: {id:0}">
{{member.id}}
</div>
<hr>
<div ng-repeat="member in list | orderBy: '-count' | filter: {id : '!0'}">
{{member.id}}
</div>
</div>
</div>
I also would suggest using the db query to provide the ordering of your elements. However, we don't always have access to change a backend or how it functions.
SO ..
I would suggest using a sort function to convert your response data before setting $scope.customers
$http.get('config/get/getCustomers.php', { cache: true }).then(function (response) {
var temp = response.data.customers.customer;
temp.sort(fucntion (item1, item2) {
if (item1.product === item2.product) {
if (item1.size === item2.size) {
return item1.color > item2.color;
}
return item1.size > item2.size;
}
return item1.product > item2.product;
}
$scope.customers = temp
});

How to add search for select in materialize css framework

I am new in materialize CSS framework and I am looking for searchable select.
I have added select component but now I want it to be searchable so that user can search value from dropdown options and select the value.
Thanks in advance
Another solution to this problem is to set minLength:0 when using Autocomplete - this essentially triggers the dropdown options on focus, and allows for searching or selecting.
The HTML:
<input type="text" id="autocomplete-input" class="autocomplete">
<label for="autocomplete-input">Autocomplete</label>
The JS:
var elems = document.querySelectorAll('.autocomplete');
var instances = M.Autocomplete.init(elems, {
data: {
"Apple": null,
"Microsoft": null,
"Google": 'https://placehold.it/250x250'
},
minLength: 0,
});
Codepen here.
I have been searching for this option for quite a while. After digging deeper into materialize Git Hub threads found this answer from LeMinaw
he got everything nailed out. but he was using a custom materialize file and also it wasn't working on the mobile. So, I have modified the code to fix mobile issue. Please use import the following script file after you imported the Materialize.js file MaterilizeSelect.js.
and format your select as following
<div class="input-field col s6">
<select data-id="26" id="MySelct" serachname="myselectsearch" searchable="your placeholder for seach box">
<option value="some1">Some One</option>
<option value="SeamSeam">SeamSeam</option>
<option value="toott">Toott</option>
<option value="Flat">Flat</option>
</select>
<label for="roof_type">My Select</label>
</div>
serachname --> A meaning fullname for search box
searchable --> placeholder your search box(label)
Hope this helps. Once again thanks to LeMinaw
There is an open issue on github.
LeMinaw's solution:
Improvements :
No need to modify Materialize JS files Grabs keyboard focus nicely No
need for annoying JQuery Renders correctly for any widget width Demo
The code is avalaible in this gist :
https://gist.github.com/LeMinaw/52675dae35531999e22f670fb66d389b
To use it, just load this JS file and add searchable="placeholder" to
your select element.
Materialize's search option just isn't great. You could work with these to try to "fix" it, but you're better off just utilizing a better select javascript package, like Select2, which does all this easily. https://select2.org/getting-started/installation
I use materialize for lots of things, but always strengthen it with Select2 (and some other form UI libraries).

Angularjs object-property

I am using this Angular Module but I can not get the work with nested data.
Here is my PLUNKR my output shows country when using object-property="country but when I try to show only states, it doesn't work.
<div class="mrg-top50">
<label>1. Autocomplete field - options list as array of objects</label>
<multiple-autocomplete ng-model="skills" object-property="country" suggestions-arr="skillsList"></multiple-autocomplete>
<label>Selected Model Value : <br />
</label>
{{skills}}
</div>
I could do it in your fiddle like this:
<multiple-autocomplete ng-model="skills" object-property="labels" suggestions-arr="skillsList[0].states"></multiple-autocomplete>
Though this is really dependent on the [0] index , which means only useful when you have just one element in the given array like in the given example.

how to separate two set of data in typehead Angular input search box?

I am trying to build a search box autocomplete using Angular Bootstrap. When I start typing in the input fields, i would like the autosuggest output(html) to be something like this:
Categories
art
science
math
Courses
algebra
biology
painting
The results are split into parts - categories and courses based on two arrays. This is what i have for the angular controller
$scope.courseSearchList = $http.get('api/courses', {cache: false});
$scope.categorySearchList = $http.get('api/categories', {'cache': false});
$q.all([$scope.categorySearchList, $scope.courseSearchList]).then(function(values) {
var a = values[0].data;
var b = values[1].data;
var c = [];
c.push(a);
c.push(b);
console.log(c[0], 'categories');
console.log(c[1], 'courses');
$scope.searchResults = c;
});
so scope.searchResults will have two arrays inside [[obj],[obj]]. The first array contains all the categories' titles and the second array contains all the courses' titles. The scope is called by the input field, here it is below
<div class="custom-typehead">
<input type="text" ng-model="selected" placeholder="search a course"
uib-typeahead="items.title for items in searchResults | filter:$viewValue:startsWith" typeahead-template-url="searchResults.html"
typeahead-on-select="onSelect($item, $model, $label)" typeahead-min-length="1" class="form-control" ng-init="">
</div>
<script type="text/ng-template" id="searchResults.html">
<div>
<div>
courses
{{match.model[0].title}}
</div>
<div">
categories
{{match.model[1].title }}
</div>
</div>
</script>
I know the script and the input are wrong, but I'm still trying to find a way to split the results in two parts like the desired output above; or maybe you can offer a better solutions to this problem. Can anyone help me with this problem? Brand new to Angular and still learning this cool framework.
Your help will be much appreciated. Thanks in advance!
Looks like you are working in angular-bootstrap framework. If it is then this link may help you.
You can use md - autocomplete material angle this is link https://material.angularjs.org/latest/demo/autocomplete
I hope to be of assistance.

How to share information between HTML and Dynamic Selections? - AngularJS

I am new to the AngularJs framework and I need some help with a couple questions.
I have tried to find information on the internet and by looking through tutorials but many of them are incomplete.
I have another problem: I must make a Web Application that will run on Phone Gap, but I don't know how to use a client side language. And I cant use JSP, etc
I read a Json file that's hosted on the server and parsed by Angular. Now when I want to do something with information I cant find how.
First: I want to take the number of the people that use the Tablet/Movil (like a loggin but not a loggin)
HTML part
<body>
<div ng-app="index" ng-controller="Ctrl1">
<p>
Indicar numero del grupo <input type="text" ng-model="numero">
</p>
Continuar
</div>
Looking on internet I find that you can use the following controller:
var app = angular.module('index', []);
app.factory("MyService", function() {
return {
data : {}
};
app.controller("Ctrl1", function($scope, $location, MyService) {
$scope.goTo2 = function() {
MyService.data.numero = $scope.numero;
$location.url("sugerencias.html");
};
app.controller("Ctrl2", function($scope, MyService) {
$scope.numero= MyService.data.numero;
And the HTML
<body>
<h1>Carta de Pedidos</h1>
<div ng-controller="Ctrl2">
<p>El numero de personas interesadas es : {{numero}}</p>
</div>
Obviously it doesn't work, and I need a small example that can help me to understand How to send the params to other
HTML
Second problem:
When I make a table with information by Json (dynamic information), that has a check box in each row, How can i know which row has been checked?
It`s possible that this question will be easy to experts but I am sure that I have not found the answer on the internet yet so I'm trying here.
Thanks to all people!!! =)
After looking many information on other pages and documentation, Angular its only used to make ONE PAGE webs. This kind on work its not eficcient on this framework. You must use differents divs that share information between them but dont move the information to other HTMLS.

Categories

Resources