To limit number of items to be displayed in react predictive input - javascript

Implementing React from couple of months. I used 'react-predictive-input' for predicting items from the pre-defined list on onchange event.
With "large" data sets (500/1000 items) the AutoComplete component becomes very slow especially when typing the first 3 characters because it will render many items in the dropdown slowing the entire interface, even using a maxHeight for the component.
Do we have any attribute as 'max-items' to show from the list?
Below is the snippet of code :
<Autocomplete
id="items"
placeholder="My Items"
data={this.props.items}
onSelected={this.onItemSelected.bind(this)} />
Function is invoked if item is selected
onItemSelected(value){
console.log(`${value} was selected`);
}
List of items
static defaultProps = {
items:[
'car','Bicycle','Truck','Green Van'............................1000items]
};
Text prediction works fine, speed and display are becoming an issue to handle.

I used Material UI Autocomplete for retrieving the use cases mentioned in the question. Link for reference here.

Related

Vue JS - Add dynamic component based on dropdown selection

I am new to Vue JS and I have below requirement
Requirement :
I have dropdown with below values
On selection of each value, I want to add dropdown component on page, which are already defined.
For example:
On Selection of 'Closed', dropdown component (which is searchable dropdown)will be added
On Selection of 'Reviewed', another dropdown component where user can select values from dropdown. (not searchable one). Likewise..
What I have :
I already have all the different types of dropdowns as a component.
What I tried :
I have loaded all the four types of dropdown on page load, and I am hiding and showing them based on dropdown value selection.
Example: I am showing only searchable dropdown component when user select 'Closed' option and hiding other components. I am showing selectable dropdown component when user select 'Reviewed' option and hiding other components.
Problem :
Now the requirement is, user can select any option N number of times and on each selection, respective dropdown component should get added.
This screen also have edit functionality.
Note :
Consider this as a filter functionality with below screen
Any help / pointers would be appreciated. Thanks in advance.
First you should create Closed and Reviewed components
Then, you should have a array of filters:
data() { return {
filters: [],
} }
When Add filter is clicked you should push corresponding component to filters, something like:
methods: {
addFilter() {
const component = Created /* */;
this.filters.push({
value: null,
component: component
})
}
}
And finally render them in template this way:
<div v-for="(filter, index) in filters" :key="index">
<component :is="filter.component" />
</div>
Demo
For And/Or dropdowns, you can use some hacks but I'm not sure how to implement them (you can check if index is zero to only display them between filters)

Is there a way to run this script in a sequence?

For context I've made a script to assign a localstorage item based on what the user selects, this item may contain "S10" but could also contain many other values, for this example the user has selected "S10"
This has now stored into localstorage.
I have created this script that I have placed in each of the product grid includes, so this script will load multiple times for each product:
window.onload = function() {
const string = localStorage.getItem('MyfitmentList', JSON.stringify(myfitment) );
const attr = {{ product.metafields['fitment']['fitment'] | json }};
document.getElementById("fitment").innerHTML = (`${string.includes(attr) ? '✔' : 'not a fit' }`);
}
Each product grid also features this container <div id="fitment"></div>
The script above loads individually for each product grid card and has it's own seperate values for "attr". If "attr" doesn't contain "S10" (which the user previously selected) then it should show "not a fit", but if the product does contain "S10" then it should show the tick.
The problem I'm having is that this only works for the first script, on the first <div id="fitment"></div> container. I can see that each individual script has a different "attr" value which is good, but I don't know why only the first container is populated.
Each script should run individually and populate the "fitment" container within it's own product card. I'm a bit at a loss as to how to do it.
Also this is on Shopify - Someone below has recommended using a single script with a loop, but in that case how would I retrieve a unique "attr" value each time the script loops? this would still leave the question of how to populate each fitment container with the correct message for each product.
Any help would be really appreciated!

Render props method without nesting dom element

In essence I have the following inside a react functional component:
<div className="content">
<div className="filters">
<MyFilter1 data={data}>
{(filter1Data) => {
return <MyFilter2 data={filter1Data}>
{(finalData) => {
return <div className="final-data">{finalData}</div>
}}
</MyFilter2>
}}
</MyFilter1>
</div>
<div className="filtered" />
I am using multiple filters with the render children paradigm to get the final data. But for (admittedly frustrating) styling reasons, I would like to render the final data in a div outside of the filters location (inside the 'filtered' div in this case). How can I do this? Is my approach wrong? Is the 'filter with render children' the wrong approach?
I have tried:
React portal with createRef(), in essence the problem ends up being that the ref is not available yet when the 'finalData' function is called.
Edit:
The filter components themselves are very complicated but I can give a couple examples. The data I'm filtering is a simple object with 12ish properties. One of the filters is implemented as a series of checkboxes determining which properties of the data I want to display (necessary as a separate component because of the number of fields). One of the properties on the data is a price, and another filter is a price range 'dialer', that specifies the price range to display ( aka exclude data points outside the range).

Angular 2 change template input values on click

Working with a set of column components with id input in my template:
<div class="panel-body" *ngIf="columns">
<div class="col-md-4">
<column [id]=columns[current_left_column].Id></column>
</div>
<div class="col-md-4">
<column [id]=columns[current_middle_column].Id></column>
</div>
<div class="col-md-4">
<column [id]=columns[current_right_column].Id></column>
</div>
</div>
I have buttons that increment and decrement the columns by changing the values of current_left_column, current_middle_column, and current_right_column. When I click those buttons I log the values of the three column id's and they're representative of where they should be however the template doesn't reload.
I did attempt to use ApplicationRef.tick() to trigger change detection, but the fact that it didn't change makes me think it's a binding issue, but I'm thus far unable to find anything that matches my case as 2-way binding seems to necessitate a more traditional input element and it currently is one way bound.
I think you need to change the name of the input. I have seen it several times that it collides with the id property every HTML element has.
I really appreciate the comments and info given, it helped me get a better handle on what I was actually trying to do.
I ended up taking an example from a different answer and using ngModel with an input to show the individual column id's. Then since I could prove my id's were switching but it wasn't updating even with the tick() I realized I was working on one component level too high and had to be initiating the change from the Column level. So I took the ngOnInit method that populates the columns with data and put it in a ngOnChanges() method, cleared the OnInit() because it was doubling up, and it started moving fine.
Then I had to deal with the information from the columns being added on top of the prior column, but that was relatively minor.
ngOnChanges(){
this._columnService.GetSingleColumn(this.id).subscribe(column => { this.columnData = column; });
this._cardService.GetCardsByColumnId(this.id).subscribe(cards => { this._cardColumnService.LoadCards(cards); console.log(this.cards); });
if (this.columnData == undefined) {
this.LoadDummyData();
}
}

Angular Material md-chips not refreshing correctly

I am developing an app that works with a "Widget layout".
The user gets a page which is a Dashboard with different widgets he can interact with, such as a table, graphs etc.
I am adding a global "filter" using <md-chips>, the objective of this is having filters that are shared by all the widgets and can be updated by all the widgets.
My Filter list uses <md-chips>, with read-only and md-removable set to True. So filters can only be deleted, or added by interacting with the widgets (so only added programmatically).
One of the feature of this "module" is to add a new filter on a field when a Graph element is clicked.
Example :
Here is my Filters list before clicking a Graph element
Now I click on a Graph element which is in a Child controller of my Filter controller, it will $emit an event to say to the global controller : "I want to update the filters ! here is the filter to add"
And the Filter Controller will get that event and update his filters accordingly ($scope.tags is the list of filters and the model used in <md-chips>)
// CHIPS
$scope.tags = [];
$scope.readOnly = true;
$scope.removable = true;
// FILTER LISTENER
$scope.$on('filterChildChanged', function (event, filter) {
$scope.tags.push(filter);
console.log($scope.tags);
console.log("Parent event fired !");
});
At that point I would expect the <md-chips>element to refresh, because $scope.tags just got a new filter :
<md-chips
ng-model="tags"
readonly="readOnly"
md-removable="removable"
id="filters">
<md-chip-template>{{$chip.value}}</md-chip-template>
</md-chips>
But instead, nothing happens! and the weird part is, it refreshes when I click on one of the existing chip (I had a "test" chip) !
TESTS :
So when I push a test chip on the array before rendering :
$scope.tags.push({field: "testField", value: "test"});
And click on a bunch of Graph elements, $scope.tags is perfectly updated, BUT the visual stays the same until I select the chip "test", then all the <md-chips> appear just like it triggered some refresh function.
Any hint on why the <md-chips> element is not refreshed as $scope.tags (its model) is updated BUT is updated when a chip is selected ?
I tried to trigger md-on-select to force this behavior to happen every time I add a new filter to $scope.tags but I got no luck so far !
Thanks for reading !
NOTE : I am using the latest version of Angular MATERIAL (HEAD MASTER) see doc here : https://material.angularjs.org/HEAD/ | built from the GitHub repository.
EDIT : The problem comes from $$hashKey not being added to the objects, they are only added when I click on one of the existing tags, I need to find a way to add this $$hashKey attribute when I add a new filter
The problem came from the absence of $$hashKey when I added a new filter to my filters model for my chips ($scope.tags).
So I just needed to change
$scope.tags.push(filter);
to
$scope.$apply(function () {
$scope.tags.push(filter);
});
And here is my console.log test
Good thing I learned :
the <md-chips> directive only knows it needs to be updated if its <chip> objects have a $$hashKey
See this on scope.$apply

Categories

Resources