how can i do, i want mi searchbar works, im doing an app, on IONIC VSCODE
Here my
HTML HERE I WANT THE SEARCHBAR WORKS
<ion-item *ngFor="let interes of interesesObj">
<ion-label>{{interes.Nombre}}</ion-label>
<ion-checkbox slot="start" [(ngModel)] ="interes.isChecked"></ion-checkbox>
AND HERE THE SEARCHBAR
<ion-item>
<ion-searchbar
[(ngModel)]="miBuscador"
[showCancelButton]="miStringDeCancell"
(ionInput)="onInput($event)"
(ionCancel)="onCancel($event)">
</ion-searchbar>
`
In HTML
<ion-searchbar mode="ios" [(ngModel)]="searchTerm" (ionClear)="setFilteredItems()"
(ionChange)="getItems($event)" placeholder="Search Topic"></ion-searchbar>
In Ts
getItems(query) {
console.log(query)
this.resetChanges();
this.posts = this.filterItems(query.detail.value);
}
protected resetChanges = () => {
this.posts = this.dummyPost;
};
setFilteredItems() {
//console.log('clear')
this.posts = [];
this.posts = this.posts;
}
filterItems(searchTerm) {
return this.posts.filter((item) => {
return item.title.toLowerCase().indexOf(searchTerm.toLowerCase()) > -1;
});
}
Related
how can I dynamically change the variant of a react-bootstrap button?
https://react-bootstrap.github.io/components/buttons/
// highlight button with correct answer
var button = document.getElementsByTagName("button");
for (var i = 0; i < button.length; i++) {
if (button[i].innerHTML === this.state.question.answer) {
//How to do that?
react-bootstrap.Button btn = button[i];
btn.variant = "success";
}
}
}
Thanks and kind regards
Update with solution options:
Option 1 do not change the variant, simply add css class with CSS The !important rule.
// highlight button with correct answer
var button = document.getElementsByTagName("button");
for (var i = 0; i < button.length; i++) {
if (button[i].innerHTML === this.state.question.answer) {
//How to do that?
button[i].classList.add("btn-correct");
}
}
}
Option two use props and state:
<div>
<DynamicButton btnVariant={this.state.btnVariant} content="Primary" />
</div>
<div>
<Button variant="secondary" onClick={this.changePrimaryButton}>Secondary</Button>
</div>
changePrimaryButton = () => {
console.log("change Button");
this.setState({ btnVariant: "success" });
}
Component outside of class:
export const DynamicButton = (props) => {
return (<Button variant={props.btnVariant}>{props.content}</Button>);
}
You can dynamically pass the variant from the parent component to this DynamicButton component.
const DynamicButton = (props) => {
return <Button variant={props.variant}>{props.content}</Button>;
}
This is how you can call this component.
<>
<DynamicButton variant="primary" content="Primary" />
</>
Please import the respective Components.
I would like to add a progress indicator to Tesseract.js logging.
The example in docs works just fine, until setting a state hook into logger:
const worker = createWorker({
logger: (m) => {
setProgress(m) //new
}});
...
const [ocr, setOcr] = useState('Recognizing...');
const [progress, setProgress] = useState(null); //new
...
return (
<div className="App">
<p>
<LogComponent progress={progress}/> //new
</p>
</div>);
This causes the browser to slow down significantly (probably due React's way to re-render on each state update). Is there a way to get around this? Using React.memo perhaps?
You could design it into a hook so your entire component doesn't re-render. Here is a useTesseract hook you can use that I created: https://gist.github.com/KevinDanikowski/25cdcdda2ef4750bcf443f2027cc375a
Copy and Pasted:
import { useState, useEffect } from 'react'
import { createWorker } from 'tesseract.js'
export default function useTesseract({ tesseractLanguage = 'eng', log = false }) {
const [tesseractWorker, setTesseractWorker] = useState(null)
const [loadingModel, setLoadingModel] = useState(true)
const [modelError, setModelError] = useState(false)
const [imgResults, setImgResults] = useState({})
const [processing, setProcessing] = useState(false)
const [progress, setProgress] = useState(0)
const extractTextFromImage = (imageUrl) => {
const recognize = async () => {
const {
data: {
hocr: htmlOutput,
text,
// tsv, box, unlv
},
} = await tesseractWorker.recognize(imageUrl)
setProcessing(false)
setImgResults({ html: htmlOutput, text })
}
if (loadingModel) {
try {
setTimeout(recognize, 400)
} catch (e) {
console.error('Timeout Error:', e.message)
setImgResults({ error: true })
}
} else {
try {
setProcessing(true)
recognize()
} catch (e) {
console.error('Tesseract Error:', e.message)
setProcessing(false)
setImgResults({ error: true })
}
}
}
const logger = (m) => {
setProgress(m.progress)
if (log) {
console.info(m)
}
}
useEffect(() => {
const loadTesseract = async () => {
if (tesseractWorker) {
await tesseractWorker.loadLanguage(tesseractLanguage)
await tesseractWorker.initialize(tesseractLanguage)
console.info(`INFO: loaded ${tesseractLanguage} tesseract model`)
} else {
const tesseractWorker = createWorker({
logger,
// specify paths because sometimes the free CDN goes down
// corePath: '/static/tesseract-core.wasm.2.2.0.js',
// workerPath: '/static/tesseract-worker.v2.1.4.min.js',
})
setTesseractWorker(tesseractWorker)
await tesseractWorker.load()
await tesseractWorker.loadLanguage(tesseractLanguage)
await tesseractWorker.initialize(tesseractLanguage)
console.info(`INFO: loaded ${tesseractLanguage} tesseract model`)
setLoadingModel(false)
setModelError(true)
setLoadingModel(false)
}
}
loadTesseract().catch((e) => {
console.error(`ERROR: Failed to load tesseract model`, e.message)
setModelError(true)
setLoadingModel(false)
})
// TODO: Have to add a ref to reference the latest tesseractWorker in order to terminate
// return () => tesseractWorker.terminate()
}, [tesseractLanguage])
return {
imgResults,
loadingModel,
processing,
modelError,
progress,
extractTextFromImage,
}
}
I managed to implement and render the progress of the tesseract worker by putting my application render inside a class and using the setState method:
class App extends React.Component {
constructor(props){
super(props)
this.state = {
file: null
}
this.handleChange = this.handleChange.bind(this)
}
setProgress(m) {
if (m.progress !== 0 && m.progress !== 0.5 && m.progress !== 1){
var prog = "Progress: " + Math.round(m.progress*100) + "%"
this.setState({progress: prog})
}
}
worker = createWorker({
logger: m => this.setProgress(m),
});
doOCR = async () => {
await this.worker.load();
await this.worker.loadLanguage('eng');
await this.worker.initialize('eng');
const { data: { text } } = await this.worker.recognize(this.state.file);
this.setState({text: extractTotal(text),
progress: ""});
};
handleChange(event) {
this.setState({text: placeholder});
this.setState({
file: URL.createObjectURL(event.target.files[0]),
})
this.doOCR()
}
setText(input){
if (!input) {
return "Please select a receipt"
}
else {
return input
}
}
render() {
console.log("Text: " + this.state.text)
return (
<div className="container">
<p>{this.setText(this.state.text)}</p>
<p>{this.state.progress}</p>
<input type="file" onChange={this.handleChange}/>
<img src={this.state.file} className='logo' alt=""/>
</div>
);
}
}
This is my code
<button v-if="$can('permission-a')">Add User</button>
<button v-if="$can('permission-b')">Add Employee</button>
And this is my $can method
data() {
return {
returnAccess: false
};
},
methods: {
$can(permissionName) {
let route = window.routes.permission;
let returnAccess;
axios
.get(route + `/${permissionName}`)
.then(resounse => {
if (resounse.data == 101) {
this.returnAccess = true;
}
})
.catch(error => {
this.returnAccess = false;
});
return this.returnAccess;
},
}
$can method return false for add user button and return true for add employee button. But add user button also showing because of true return for add employee button.
How can i solve this issue. Any one can help me?
Thanks in advance.
First of all you don't need to return a value
create a permissions object:
data() {
return {
permissions: {}
};
and a method like:
methods: {
$can(permissionName) {
let route = window.routes.permission;
let returnAccess;
axios
.get(route + `/${permissionName}`)
.then(resounse => {
if (resounse.data == 101) {
this.permissions.permissionName = true;
}
})
.catch(error => {
this.permissions.permissionName = false;
});
},
}
now foreach this in your created()
created() {
let permissionNames = ['a', 'b'];
permissionNames.forEach(function(permissionName) {
this.$can(permissionName) {
});
}
this way you create a object with keys as the permisson.
now in html you can simple do:
<button v-if="permission.somePermission">Add User</button>
<button v-if="permission.somePermission">Add Employee</button>
NOTE: not tested, but hope you get the idea
I'm trying to validate a form with tags, where the list must contain at least one tag to be valid. But it's only evaluating when the page loads, and not updating.
https://plnkr.co/edit/umnhybKhNEjswrUJGh3q?p=preview
Validation Function:
function notEmpty(control) {
if(control.value == null || control.value.length===0) {
return {
notEmpty: true
}
}
return null;
}
Component and Template using the Validator:
#Component({
selector: 'my-app',
template: `
<form [formGroup]="myForm">
<div>
(Comma Separated, no duplicates allowed. Enter also submits a tag.)
<div tags formControlName="list" [(ngModel)]="list"> </div>
<div *ngIf="myForm.get('list').valid">List 1 Not Empty.</div>
<div tags formControlName="list2" [(ngModel)]="list2"> </div>
<div *ngIf="myForm.get('list2').valid">List 2 Not Empty.</div>
</div>
</form>
`,
})
export class App {
list:Array<string>;
list2:Array<string>;
myForm:FormGroup;
myList:FormControl;
myList2:FormControl;
constructor(private fb: FormBuilder) {
this.list = [];
this.list2 = ["test"];
this.myList = fb.control('', notEmpty);
this.myList2 = fb.control('', notEmpty);
this.myForm = fb.group({
list: this.myList,
list2: this.myList2
});
}
addItem(item:string) {
this.list.push(item);
}
}
Tags Component and other child components:
const MY_PROVIDER = {
provide: NG_VALUE_ACCESSOR,
useExisting: forwardRef(()=> Tags),
multi: true
};
#Component({
selector: 'tags, [tags]',
template: `
<div>
<tag-item *ngFor="let item of tagsList" item="{{item}}" (remove)="removeTag(item)"></tag-item>
<input class="tagInput" #tagInput
(focus)="focus()"
[(ngModel)]="current"
(keydown)="keyDown($event)"
(keyup)="keyUp($event)"
(blur)="blur()"
placeholder="+ Tag"/>
</div>
`,
providers: [MY_PROVIDER]
})
export class Tags implements ControlValueAccessor {
tagsList : Array<string>;
current : string;
#ViewChild('tagInput') child;
inFocus : boolean = false;
constructor() {
this.current = "";
this.tagsList = new Array<string>();
}
focus() {
this.child.nativeElement.focus();
this.inFocus = true;
}
keyDown(event:KeyboardEvent) {
if (event.keyCode === 188 || event.keyCode === 13) { //188 is Comma, 13 is Enter, 32 is Space.
this.pushTag();
} else if (event.keyCode === 8 && this.current.length == 0 && this.tagsList.length > 0){
this.current = this.tagsList.pop();
}
}
keyUp(event:KeyboardEvent) {
if(event.keyCode === 188) {
this.current = '';
}
}
pushTag() {
let str = this.current;
this.current = '';
if(str.trim() != '') {
for(let s of str.split(',')) {
s = this.sanitize(s);
if(s.trim() != '') {
if(!this.tagsList.some(x => x.toLowerCase() === s.toLowerCase()))
this.tagsList.push(s);
}
}
}
}
sanitize(str: string) : string {
let s = str;
s = s.replace('\'', '').replace('"', '').replace(';', '');
return s;
}
blur() {
this.pushTag();
this.inFocus = false;
}
removeTag(value) {
let index = this.tagsList.indexOf(value, 0);
if (index > -1) {
this.tagsList.splice(index, 1);
}
}
clear() {
this.tagsList = new Array<string>();
}
get value(): Array<string> { return this.tagsList; };
set value(v: Array<string>) {
if (v !== this.tagsList) {
this.tagsList = v;
this.onChange(v);
this.onTouched();
}
}
writeValue(value: Array<string>) {
this.tagsList = value;
this.onChange(value);
}
onChange = (_) => {};
onTouched = () => {};
registerOnChange(fn: (_: any) => void): void { this.onChange = fn; }
registerOnTouched(fn: () => void): void { this.onTouched = fn; }
}
#Component({
selector: 'tag-item, [tag-item]',
template: `{{item}} <delete-me (click)="removeTag(item)">x</delete-me>`
})
export class TagItem {
#Input() item : string;
#Output() remove : EventEmitter<string> = new EventEmitter();
removeTag(item) {
this.remove.emit(item);
}
}
#Component({
selector:'delete-me',
template:'x'
})
export class DeleteIcon {
}
This seems to work.
...//Tags Component pushMethod
pushTag() {
let str = this.current;
this.current = '';
if(str.trim() != '') {
for(let s of str.split(',')) {
s = this.sanitize(s);
if(s.trim() != '') {
if(!this.tagsList.some(x => x.toLowerCase() === s.toLowerCase())) {
this.tagsList.push(s);
this.pushed.emit(s); // created an EventEmitter<string>
}
}
}
}
}
And in my main component:
#Component({
selector: 'my-app',
template: `
<form [formGroup]="myForm">
<div>
(Comma Separated, no duplicates allowed. Enter also submits a tag.)
<div tags formControlName="list" (pushed)="update()" [(ngModel)]="list"> </div>
<div *ngIf="myForm.get('list').valid">List 1 Not Empty.</div>
<div tags formControlName="list2" (pushed)="update()" [(ngModel)]="list2"> </div>
<div *ngIf="myForm.get('list2').valid">List 2 Not Empty.</div>
</div>
</form>
`,
})
export class App {
list:Array<string>;
list2:Array<string>;
myForm:FormGroup;
myList:FormControl;
myList2:FormControl;
constructor(private fb: FormBuilder) {
this.list = [];
this.list2 = ["test"];
this.myList = fb.control('', notEmpty);
this.myList2 = fb.control('', notEmpty);
this.myForm = fb.group({
list: this.myList,
list2: this.myList2
});
}
update() {
this.myList.updateValueAndValidity();
this.myList2.updateValueAndValidity();
}
addItem(item:string) {
this.list.push(item);
}
}
Seems kind of hacky, though, so I'd still like a better answer, if there is one.
I have a ReactJS component that I want to have different behavior on a single click and on a double click.
I read this question.
<Component
onClick={this.onSingleClick}
onDoubleClick={this.onDoubleClick} />
And I tried it myself and it appears as though you cannot register both single click and double click on a ReactJS component.
I'm not sure of a good solution to this problem. I don't want to use a timer because I'm going to have 8 of these single components on my page.
Would it be a good solution to have another inner component inside this one to deal with the double click situation?
Edit:
I tried this approach but it doesn't work in the render function.
render (
let props = {};
if (doubleClick) {
props.onDoubleClick = function
} else {
props.onClick = function
}
<Component
{...props} />
);
Here is the fastest and shortest answer:
CLASS-BASED COMPONENT
class DoubleClick extends React.Component {
timer = null
onClickHandler = event => {
clearTimeout(this.timer);
if (event.detail === 1) {
this.timer = setTimeout(this.props.onClick, 200)
} else if (event.detail === 2) {
this.props.onDoubleClick()
}
}
render() {
return (
<div onClick={this.onClickHandler}>
{this.props.children}
</div>
)
}
}
FUNCTIONAL COMPONENT
const DoubleClick = ({ onClick = () => { }, onDoubleClick = () => { }, children }) => {
const timer = useRef()
const onClickHandler = event => {
clearTimeout(timer.current);
if (event.detail === 1) {
timer.current = setTimeout(onClick, 200)
} else if (event.detail === 2) {
onDoubleClick()
}
}
return (
<div onClick={onClickHandler}>
{children}
</div>
)
}
DEMO
var timer;
function onClick(event) {
clearTimeout(timer);
if (event.detail === 1) {
timer = setTimeout(() => {
console.log("SINGLE CLICK");
}, 200)
} else if (event.detail === 2) {
console.log("DOUBLE CLICK");
}
}
document.querySelector(".demo").onclick = onClick;
.demo {
padding: 20px 40px;
background-color: #eee;
user-select: none;
}
<div class="demo">
Click OR Double Click Here
</div>
I know this is an old question and i only shoot into the dark (did not test the code but i am sure enough it should work) but maybe this is of help to someone.
render() {
let clicks = [];
let timeout;
function singleClick(event) {
alert("single click");
}
function doubleClick(event) {
alert("doubleClick");
}
function clickHandler(event) {
event.preventDefault();
clicks.push(new Date().getTime());
window.clearTimeout(timeout);
timeout = window.setTimeout(() => {
if (clicks.length > 1 && clicks[clicks.length - 1] - clicks[clicks.length - 2] < 250) {
doubleClick(event.target);
} else {
singleClick(event.target);
}
}, 250);
}
return (
<a onClick={clickHandler}>
click me
</a>
);
}
I am going to test this soon and in case update or delete this answer.
The downside is without a doubt, that we have a defined "double-click speed" of 250ms, which the user needs to accomplish, so it is not a pretty solution and may prevent some persons from being able to use the double click.
Of course the single click does only work with a delay of 250ms but its not possible to do it otherwise, you have to wait for the doubleClick somehow...
All of the answers here are overcomplicated, you just need to use e.detail:
<button onClick={e => {
if (e.detail === 1) handleClick();
if (e.detail === 2) handleDoubleClick();
}}>
Click me
</button>
A simple example that I have been doing.
File: withSupportDoubleClick.js
let timer
let latestTouchTap = { time: 0, target: null }
export default function withSupportDoubleClick({ onDoubleClick = () => {}, onSingleClick = () => {} }, maxDelay = 300) {
return (event) => {
clearTimeout(timer)
const touchTap = { time: new Date().getTime(), target: event.currentTarget }
const isDoubleClick =
touchTap.target === latestTouchTap.target && touchTap.time - latestTouchTap.time < maxDelay
latestTouchTap = touchTap
timer = setTimeout(() => {
if (isDoubleClick) onDoubleClick(event)
else onSingleClick(event)
}, maxDelay)
}
}
File: YourComponent.js
import React from 'react'
import withSupportDoubleClick from './withSupportDoubleClick'
export default const YourComponent = () => {
const handleClick = withSupportDoubleClick({
onDoubleClick: (e) => {
console.log('double click', e)
},
onSingleClick: (e) => {
console.log('single click', e)
},
})
return (
<div
className="cursor-pointer"
onClick={handleClick}
onTouchStart={handleClick}
tabIndex="0"
role="button"
aria-pressed="false"
>
Your content/button...
</div>
)
}
onTouchStart start is a touch event that fires when the user touches the element.
Why do you describe these events handler inside a render function? Try this approach:
const Component = extends React.Component {
constructor(props) {
super(props);
}
handleSingleClick = () => {
console.log('single click');
}
handleDoubleClick = () => {
console.log('double click');
}
render() {
return (
<div onClick={this.handleSingleClick} onDoubleClick={this.handleDoubleClick}>
</div>
);
}
};