Nativescript - Update RSSI value every second - bluetooth

currently i have one Bluetooth app which will scan all available device and able to connect to the device.
i have listview which will be display everytime it found the Bluetooth device.
however, can i know, how to make app update the RSSI value in every second?
here is my code.
doStartScanning(){
this.peripherals=[];
this.distance=[];
bluetooth.startScanning({
serviceUUIDs: [],
// seconds: 4, /*if this is not specify, user can manually stop the scanning by press button stop scan*/
onDiscovered: (peripheral) => {
this.zone.run(() => {
console.log("---UUID "+peripheral.UUID);
this.peripherals.push(peripheral);
this.distance.push(`${Math.round((Math.pow(10,(-62-(peripheral.RSSI+20))/20))*10)/10}`);
})
}
}
).then(function() {
console.log("scanning complete");
}, function (err) {
console.log("error while scanning: " + err);
});
}
/*user can stop scan the available bluetooth*/
doStopScanning(){
bluetooth.stopScanning().then(function() {
console.log("Scanning Stop!");
},
function (err) {
dialogs.alert({
title: "Whoops!",
message: err,
okButtonText: "OK, so be it"
});
});
}
<GridLayout rows="*">
<ListView [items]="peripherals" separatorColor="#90c3d4">
<ng-template let-peripherals="item" let-i="index" let-odd="odd" let-even="even">
<StackLayout orientation="horizontal" class="padded-label" >
<StackLayout class="padded-label-stack">
<Label horizontalAlignment="right" width="40" text="{{ peripherals.RSSI +20}} dBm" class="rssi-label" ></Label>
<Label horizontalAlignment="right" width="40" text="{{ distance[i] }} m" class="rssi-label" ></Label>
</StackLayout>
<StackLayout class="padded-label-stack" (tap)="onTapPeripheral(peripherals.UUID,peripherals.name, peripherals.state)">
<Label text="Name: {{ peripherals.name }}" class="title-label" textWrap="true" ></Label>
<Label text="UUID: {{ peripherals.UUID }}" class="uuid-label" textWrap="true" ></Label>
<Label text="State: {{ peripherals.state }}" class="uuid-label" textWrap="true" ></Label>
</StackLayout>
</StackLayout>
</ng-template>
</ListView>
</GridLayout>

Unfortunately reading RSSI is not yet supported by the plugin. You might have to override the CBPeripheralDelegate / BluetoothGattCallback implemented by the plugin in order to read that.

Related

Passing data from kendo grid HTML to component.ts file

I am creating a sample fullstack application in angular to do CRUD operations on employee data such as image, name, email, phone, salary and department. I am using kendo grid to show, add and edit employee data. I am using Node JS for API and Mongo DB for database.
I am able to view the employee data and add new employees to list. But i am unable to edit the details using kendo grid. I do not know how to pass value from kendo grid to .ts file.
Below is the code i am working on.
I don't know how to pass the data or update it by employee id. I have used event method but it didn't work. I tried passing dataItem through button click method as well, but it doesn't work
Help me on this.
employee-list.component.html
<form novalidate #myForm="ngForm">
<kendo-grid
[kendoGridTemplateEditing]="createNewEmployee"
[kendoGridBinding]="employees"
[pageSize]="5"
[pageable]="true"
[sortable]="true"
[navigable]="true">
<ng-template kendoGridToolbarTemplate>
<button kendoGridAddCommand type="button">Add new</button>
</ng-template>
<kendo-grid-column title="Profile Picture" [style]="{'text-align': 'center'}" [width]="200">
<ng-template kendoGridCellTemplate let-dataItem>
<img src={{dataItem.imageData}}
onerror=" this.src = './../../assets/placeholder.png' "
height="100" width="100" style="border-radius:50px;" alt="Employee Image"/>
</ng-template>
<ng-template kendoGridEditTemplate let-dataItem="dataItem">
<ng-container *ngIf="imageUrl;else elseTemplate">
<img [src]="dataItem.imageData ? dataItem.imageData : imageUrl" height="100" width="100" style="border-radius:50px;" />
</ng-container>
<ng-template #elseTemplate>
<img src="./../../assets/placeholder.png" height="100" width="100" style="border-radius:50px;">
</ng-template>
<input kendoGridFocusable class="form-control my-2" type="file" id="profileImage" accept="image/*" (change)="onFileChange($event)" required>
</ng-template>
</kendo-grid-column>
<kendo-grid-column field="_id" title="id">
<ng-template kendoGridEditTemplate let-dataItem>
<input
[(ngModel)]="dataItem._id"
kendoGridFocusable
name="ID"
class="k-textbox k-input k-rounded-md"
required
/>
</ng-template>
</kendo-grid-column>
<kendo-grid-column field="name" title="Name">
<ng-template kendoGridEditTemplate let-dataItem>
<input
[(ngModel)]="dataItem.name"
kendoGridFocusable
name="name"
class="k-textbox k-input k-rounded-md"
required
/>
</ng-template>
</kendo-grid-column>
<kendo-grid-column field="email" title="Email">
<ng-template kendoGridEditTemplate let-dataItem>
<input
[(ngModel)]="dataItem.email"
kendoGridFocusable
name="email"
class="k-textbox k-input k-rounded-md"
/>
</ng-template>
</kendo-grid-column>
<kendo-grid-column field="phone" editor="numeric" title="Phone">
<ng-template kendoGridEditTemplate let-dataItem>
<input
[(ngModel)]="dataItem.phone"
kendoGridFocusable
name="phone"
type="number"
/>
</ng-template>
</kendo-grid-column>
<kendo-grid-column field="salary" editor="numeric" title="Salary">
<ng-template kendoGridEditTemplate let-dataItem>
<input
[(ngModel)]="dataItem.salary"
kendoGridFocusable
name="salary"
required
class="k-textbox k-input k-rounded-md"
type="number"
/>
</ng-template>
</kendo-grid-column>
<kendo-grid-column field="department" title="Department">
<ng-template kendoGridEditTemplate let-dataItem="dataItem">
<input
[(ngModel)]="dataItem.department"
kendoGridFocusable
name="department"
required
class="k-textbox k-input k-rounded-md"
/>
</ng-template>
</kendo-grid-column>
<kendo-grid-command-column title="command" [width]="220">
<ng-template kendoGridCellTemplate let-isNew="isNew">
<button kendoGridEditCommand type="button" [primary]="true">
Edit
</button>
<button kendoGridRemoveCommand type="button">Remove</button>
<ng-container *ngIf="isNew; else update">
<button kendoGridSaveCommand [disabled]="!myForm.valid" (click)="addEmployee()">Add</button>
</ng-container>
<ng-template #update>
<button kendoGridSaveCommand [disabled]="!myForm.valid" (click)="updateEmployee()">Update</button>
</ng-template>
<button kendoGridCancelCommand type="button">
{{ isNew ? "Discard changes" : "Cancel" }}
</button>
</ng-template>
</kendo-grid-command-column>
</kendo-grid>
</form>
employee-list.component.ts
export class EmployeesListComponent implements OnInit{
employees: Employee[] = [];
baseApiUrl: string = environment.baseApiUrl;
image: File = null;
imageUrl: string;
employeeDetails: Employee = {
_id: '',
name: '',
email: '',
phone: 0,
salary: 0,
department: '',
imageData: '',
selected: false
};
constructor(
private employeesService: EmployeesService,
private router: Router,
private httpClient: HttpClient
) {}
ngOnInit(): void {
this.employeesService.getAllEmployees().subscribe(
dataEmployees => this.employees = dataEmployees
);
}
onFileChange(event){
this.image = event.target.files[0];
const reader = new FileReader();
reader.readAsDataURL(this.image);
reader.onload = () => {
this.imageUrl = reader.result as string;
};
}
createNewEmployee(): Employee {
return new Employee()
}
addEmployee(){
this.employeesService.addEmployee(this.employees[0], this.image).then(
(response) => {
this.router.navigate(['']);
console.log(this.employees[0].department);
},
(error) => {
console.log(error);
}
);
}
updateEmployee(){
this.employeesService.updateEmployee(this.employeeDetails._id, this.employeeDetails, this.image).then(
(response) => {
this.router.navigate(['']);
},
(error) => {
console.log(error);
}
);
console.log("employee edit")
}
}
I am using employeeDetails to store the updated data and pass it on to service but the updated details aren't stored in it
employee.service.ts
export class EmployeesService {
baseApiUrl: string = environment.baseApiUrl;
constructor(private http: HttpClient) { }
getAllEmployees(): Observable<Employee[]>{
return this.http.get<Employee[]>(this.baseApiUrl + '/employees');
}
updateEmployee(id: string, updateEmployeeRequest: Employee, image:File){
return new Promise((resolve, reject) => {
const fileReader = new FileReader();
if(image != null){
fileReader.readAsDataURL(image);
fileReader.onload = () => {
updateEmployeeRequest.imageData = fileReader.result as string;
this.http.patch(this.baseApiUrl + '/employees/' + id, updateEmployeeRequest).subscribe(
(response) => {
resolve(response);
},
(error) => {
reject(error);
}
);
}
}
else {
this.http.patch(this.baseApiUrl + '/employees/' + id, updateEmployeeRequest).subscribe(
(response) => {
resolve(response);
},
(error) => {
reject(error);
}
);
}
});
}
}

formik for validation and post request

const classes = useStyles();
const initialValues = {
email: '',
fullName: '',
subject: '',
massage: '',
}
const onSubmit = (values) =>{
console.log("values")
axios
.post(`http://localhost:5000/sendmail/contact` , values)
.then((res) => console.log(res))
.catch((errors) => console.log(errors));
};
const formik = useFormik({
initialValues,
validationSchema,
onSubmit,
})
<form onSubmit={formik.handleSubmit}>
<Grid className={classes.GridContactHeading}>
<Typography variant="h4">Contact us</Typography>
</Grid>
<Grid className={classes.GridContactSubHeading}>
<Typography variant="h5">Feel free to ask for details, don't save any questions!</Typography>
</Grid>
<Grid container justifyContent="center">
<Grid item sm={8} md={6} className={classes.GridText1}>
<TextField
required
name='fullName'
label='Full Name'
onChange={formik.handleChange}
value={formik.values.fullName}
className={classes.TextFieldContact}
/>
{formik.errors.fullName ? <div>{formik.errors.fullName}</div> : null}
</Grid>
<Grid item sm={8} md={6} className={classes.GridText2}>
<TextField
required
id="email"
name="email"
label="Email"
fullWidth
onChange={formik.handleChange}
value={formik.values.email}
className={classes.TextFieldContact }
/>
{formik.errors.fullName ? <div>{formik.errors.email}</div> : null}
</Grid>
</Grid>
<Grid className={classes.GridText3}>
<TextField
required
id="subject"
name="subject"
label="Subject"
fullWidth
onChange={formik.handleChange}
value={formik.values.subject}
className={classes.TextFieldContact}
/>
{formik.errors.fullName ? <div>{formik.errors.subject}</div> : null}
</Grid>
<Grid className={classes.GridText3}>
<TextareaAutosize
placeholder="Massage"
minRows={15}
className={classes.AutoSizeTextfield}
id="massage"
name="massage"
onChange={formik.handleChange}
value={formik.values.massage}
/>
{formik.errors.massage ? <div>{formik.errors.massage}</div> : null}
</Grid>
<Grid>
<Button type="submit" variant="contained" color="primary" style={{marginTop:"20px", marginBottom: "20px"}} >
Send Massage
</Button>
</Grid>
</form>
i have created form and validate using formik and yup and now i have to send it to the backend as apost request and get an email but here onsubmit part doesnt work
I have a hunch that your onSubmit function is conflicting with Formik's onSubmit function. That, or your validationSchema needs to be directly declared in your useFormik object. I edited it just a bit with some format changes.
validationSchema: Yup.object({
email: Yup.string('Enter your email').email('Enter a valid
email').required('Email is required'),
fullName: Yup.string('Enter your FullName').trim()
.required('Full Name is required'),
subject: Yup.string('Enter your Subject').trim().required('subject is required'),
message: Yup.string('Enter your Message').trim().required('Message is required')
})
Please check your validationSchema logic. If this log line is not printed on submit event click, most probably the form is invalid. So check your validationSchema first. and why do you pass params to yup.string() method. https://www.npmjs.com/package/yup#string

Nativescript Angular - Cannot trigger itemSelected on the first item on a RadListView

Please help!
I cannot click the first item in the radlistview on IOS (onItemSelected is not triggered), however it is working fine on android.
My code:
<GridLayout class="p-x-10">
<RadListView
class="users"
loadOnDemandMode="Auto"
pullToRefresh="true"
selectionBehavior="Press"
[items]="userPaginator.docs"
(itemSelected)="onItemSelected($event)"
(loadMoreDataRequested)="onLoadMoreItemsRequested($event)"
(pullToRefreshInitiated)="onPullToRefreshInitiated($event)"
>
<ng-template tkListItemTemplate let-item="item">
<StackLayout orientation="vertical" class="users__card">
<Label class="users__card-name" [text]="item.name"></Label>
<Label class="users__card-username" [text]="item.username"></Label>
<Label class="users__card-userId" [text]="item.userId"></Label>
<Label class="users__card-email" [text]="item.email"></Label>
<Label class="users__card-phone" [text]="item.phone"></Label>
</StackLayout>
</ng-template>
</RadListView>
<ActivityIndicator
rowSpan="1"
[busy]="isPageLoading"
[visibility]="isPageLoading ? 'visible' : 'collapse'"
horizontalAlignment="center"></ActivityIndicator>
</GridLayout>
Instead of OnItemSelected you can use tap event of StackLayout
<StackLayout orientation="vertical" class="users__card" (tap)="onItemSelected($event)">

Angular6 Material Dialog prevent from closing when pressing enter

I have a login dialog and want to prevent it from closing automatically when enter is pressed.
To be more specific, when the user put the credential and pressed enter and the response for credential came back as error, I want the dialog to stay (so I can show them some error message and let the user try once again).
So this is what I did:
export class LoginComponent {
constructor(public dialogRef: MatDialogRef<LoginComponent>) { }
onSubmit(): void {
this.authService.login(...)
.subscribe(res => {
...
},
error => {
this.dialogRef.disableClose = true;
}
}
}
this.dialogRef.disableClose = true; still closes the dialog even though the response came back as error.
How should I do this?
Edit
login.component.ts
<mat-toolbar>
<span>Login</span>
</mat-toolbar>
<mat-card class="my-card">
<div *ngIf="error" style="color: red;">{{error}}</div><br />
<form (ngSubmit)="onSubmit()" [formGroup]="loginForm">
<mat-card-content>
<mat-form-field appearance="outline" class="full-width">
<mat-label>Email</mat-label>
<input matInput placeholder="Email"
formControlName="email"
[formControl]="emailFormControl"
[errorStateMatcher]="matcher" />
<mat-error *ngIf="emailFormControl.hasError('email') && !emailFormControl.hasError('required')">
Enter valid email address
</mat-error>
<mat-error *ngIf="emailFormControl.hasError('required')">
Required field
</mat-error>
</mat-form-field>
<mat-form-field appearance="outline" class="full-width">
<mat-label>Password</mat-label>
<input matInput type="password"
placeholder="Password"
formControlName="password"
[formControl]="passwordFormControl"
[errorStateMatcher]="matcher" />
<mat-error *ngIf="passwordFormControl.hasError('required')">
Required field
</mat-error>
</mat-form-field>
</mat-card-content>
<mat-card-actions>
<button mat-raised-button (click)="onNoClick()" color="primary">Close</button>
<button mat-raised-button
[disabled]="!(loginForm.controls.email.valid && loginForm.controls.password.valid)"
color="accent">
Login
</button>
</mat-card-actions>
</form>
</mat-card>
login.component.ts
onSubmit(): void {
if (this.loginForm.invalid) {
return;
}
this.authService.login(this.loginForm.controls.email.value, this.loginForm.controls.password.value)
.subscribe(res => {
if (res) {
alert("logged in");
}
},
error => {
this.error = 'Error! Plese try again.';
}
);
}
I believe it's because your "CLOSE" button, is not set to type="button", and I THINK that's the first element that has focus, so when pressing enter, you are entering that button, which by default, will submit the form. Add type="button" and that should solve it.
Also for the record, the latest version of angular material has md-button automatically add type="button" by default (unless you specify type="submit") to avoid this type of situation
Use this
<mat-card-actions>
<button mat-raised-button type="button" (click)="onNoClick()" color="primary">Close</button>
<button mat-raised-button type="submit"
[disabled]="!(loginForm.controls.email.valid && loginForm.controls.password.valid)"
color="accent">
Login
</button>
</mat-card-actions>

Clear Search on Semantic-ui

How do I get the selected result of a search field of Semantic-UI?
Using onSelect event, I can get the selected result, but this does not work when clean the field with the backspace.
Using field.search('get result') also not return the result blank as expected.
You can get the selected result like this:
onSelect:function(result){
console.log(result)
}
Having a sample HTML form with 2 inputs like this (one hidden):
<form id="search-box-form">
<input type="hidden" name="search" value="" />
<div class="ui search location-search">
<div class="ui icon input">
<input class="prompt" type="text" placeholder="Search locations..." />
<i class="search icon"></i>
</div>
<div class="results"></div>
</div>
</form>
The same way you use onSelect to populate your hidden field, you can use onResultsClose to clear your hidden input. Caveat: onResultsClose will run before semantic puts the value on it's own field, hence the need to use timeout function.
jQuery(document).ready(
function() {
jQuery('.location-search')
.search({
source : content,
searchOnFocus : true,
minCharacters : 0,
onSelect: function(result, response) {
var value = result.value;
$('#search-box-form').find('input[name=search]').val(value);
},
onResultsClose: function(){
setTimeout(function() {
if (jQuery('.location-search').search('get value') == '') {
$('#search-box-form').find('input[name=search]').val('');
}
}, 500);
}
})
;
}
);

Resources