Angular - electron view does not update after model changes - javascript

I have a field that enables me to choose a folder from an electron dialog. On clicking the field, the dialog opens and I'm able to select the folder.
However, upon hitting ok, even though my model contains the folder's path, it does not reflect in the input field, until I click OUTSIDE the field (when it loses focus). How exactly do I fix this behaviour?
Template contains:
<input type="text" class="form-control" (click)="onClickPath($event)" [(ngModel)]="currentConfiguration.workspacePath" id="workspace-path" name="workspace-name" aria-label="workspace" aria-describedby="workspace-lable">
CurrentConfiguration.ts
export class CurrentConfiguration {
workspacePath: string;
}
configuation.component.ts
currentConfiguration: CurrentConfiguration = {
workspacePath: ""
};
//onClickedPath event:
onClickPath(event) {
console.log("clicked: ", event.target.id);
// open the dialog to select the directory
const dir = this.electronService.remote.dialog.showOpenDialog({
properties: ["openDirectory"],
title: event.target.id.split('-').join(" ")
}, (folderPath) => {
console.log(folderPath);
if (folderPath[0] == undefined) {
this.electronService.remote.dialog.showMessageBox({
type: "error",
buttons: ["ok"],
title: "Error",
message: "Please select the folder"
});
}
else{
// set the correct directoryPath.
this.currentConfiguration[event.target.id.split('-')[0] + 'Path'] = folderPath[0];
}
});
}

Note - this is a almost a dupe of This question Since it helped me resolve the issue, I'll post the answer.
Electron dialogs seem to function outside the angular zone and hence any updates to the data does no trigger angular to refresh the view.
In order to make the refresh happen, I had to execute the logic inside a zone like below:
import { NgZone } from '#angular/core';
...
...
currentConfiguration: CurrentConfiguration = {
workspacePath: ""
};
//onClickedPath event:
onClickPath(event) {
console.log("clicked: ", event.target.id);
// open the dialog to select the directory
const dir = this.electronService.remote.dialog.showOpenDialog({
properties: ["openDirectory"],
title: event.target.id.split('-').join(" ")
}, (folderPath) => {
console.log(folderPath);
if (folderPath[0] == undefined) {
this.electronService.remote.dialog.showMessageBox({
type: "error",
buttons: ["ok"],
title: "Error",
message: "Please select the folder"
});
}
else{
// run all of this inside the zone
this.zone.run(() => {
// set the correct directoryPath.
this.currentConfiguration[event.target.id.split('-')[0] + 'Path'] = folderPath[0];
}); // end of zone
}
});
}

Related

Dynamically change a value of instance already created in JavaScript

I'm using "Braintree - Dropin" here. Instance is created when page load and I have a dropdown to select "pay amount" after. I want to update value of instance (already created) when dropdown is changed.
var form = document.querySelector('#payment-form');
var client_token = "{{ Braintree\ClientToken::generate()}}";
var amount = document.getElementById("amount");
var amount_val = amount.options[amount.selectedIndex].value;
braintree.dropin.create({
authorization: client_token,
selector: '#bt-dropin',
applePay: {
displayName: 'My Store',
paymentRequest: {
total: {
label: 'My Store',
amount: amount_val
}
}
}
}, function (createErr, instance) {
if (createErr) {
console.log('Create Error', createErr);
return;
}
amount.addEventListener("change", function() {
console.log(amount.value);
// Where i'm trying to change amount
instance.updateConfiguration('applePay', 'paymentRequest', {
total: {
label: 'My Store',
amount: amount.value
}
});
});
form.addEventListener('submit', function (event) {
event.preventDefault();
instance.requestPaymentMethod(function (err, payload) {
if (err) {
console.log('Request Payment Method Error', err);
return;
}
// Add the nonce to the form and submit
document.querySelector('#nonce').value = payload.nonce;
form.submit();
});
});
});
According to "Dropin" documentation this should work. but it doesn't.
https://braintree.github.io/braintree-web-drop-in/docs/current/Dropin.html#updateConfiguration
I couldn't find a possible way to change instance after it is created. But I solved the problem by splitting process in to two parts. I made two steps to do the payment. In first page user will select amount from dropdown then click next button which submit selected amount into payment page. then on payment page this instance is created with amount already post from previous page. Hope this will help someone with a similar issue.

angular-slickgrid, trigger the cell edit on select editor change event

I am using angular-silkgrid with angular 7. I am using inline editing feature. I am using single select editor for inline edit. Currently I want to achieve this functionality:
As soon as user click on the editable field , the select drop down will be visible.On select any option from select dropdown the inline mode should exist and column value should be updated.
currently I need to click on other field to exit from inline mode(I want to achieve this on select option select)
editor: {
// display checkmark icon when True
enableRenderHtml: true,
// tslint:disable-next-line:max-line-length
collection: [{
value: 1,
label: 'Sucessful'
}, {
value: 2,
label: 'Unsucessful'
}],
model: Editors.singleSelect, // CustomSelectEditor
elementOptions: {
autoAdjustDropPosition: false,
onClick: (event, rr) => {
// here i want to write some code which can trigger to grid to start update
}
}
}
Thanks All for the answers. I have solved my issue as below:
editor: {
enableRenderHtml: true,
collection: [{ value: CCLStaus.Sucessfull, label: 'Sucessful' }, { value: CCLStaus.UnSucessfull, label: 'Unsucessful' }],
model: Editors.singleSelect,// CustomSelectEditor
elementOptions: {
onClick: (event) => {
const updateItem = this.angularSilkGrid.gridService.getDataItemByRowIndex(this.rowInEditMode);
updateItem.status = +event.value;
this.angularSilkGrid.gridService.updateItem(updateItem, { highlightRow: false });
this.angularSilkGrid.gridService.renderGrid();
}
}
}
Generally,
grid.getEditorLock().commitCurrentEdit()
will commit and close the editor.
Also, any of
grid.navigateRight()
grid.navigateLeft()
grid.navigateDown()
grid.navigateUp()
grid.navigateNext()
grid.navigatePrev()
will commit and exit gracefully. In the select2 editor, you'll notice:
this.init = function () {
...
// Set focus back to select2 element on closing.
$input.on('select2:close', function (e) {
if ((e.params.originalSelect2Event && e.params.originalSelect2Event.data)
|| e.params.key === 9) {
// item was selected with ENTER or no selection with TAB
args.grid.navigateNext();
} else {
// closed with no selection
setTimeout(function () {
$input.select2('focus');
}, 100);
}
});
};
this.destroy = function () {
$input.select2('destroy');
$input.remove();
};
, noting that args.grid.navigateNext() will commit and close the editor, including calling the destroy() method at the appropriate time.
From the Angular-Slickgrid Editor Example there's a checkbox in the example to auto commit and that is a setting to you need to enable in your Grid Options
this.gridOptions = {
autoEdit: true,
autoCommitEdit: true,
}
The lib will internally call grid.getEditorLock().commitCurrentEdit() like Ben wrote in his answer, in Angular-Slickgrid you can just set the autoCommitEdit flag that I added.

Error on React-Native Android hardaware BackButton click "Undefined is not a function(evaluating '_this2.close()') "

I have installed the react-native-orientation-loading-overlay package for applying the loader on the screen.
When user clicks on the hardware back button, the backAndroid's addEventListener is called. Depending on the condition, loader's animating property is set to true and the orientation loader starts loading.
While loading, the another function this.fetchData() is started running which fetches data by running the webservice and display in listview of same page i.e mainPage.
And while loading, if the user has again pressed the back button the red screen with the error "Undefined is not a function(evaluating _this2.close()) in onRequestClose method of react-native-orienation-loading-overlay\src\index.js file" displays .I have tried to BackAndroid.removeEventListener('hardwareBackPress', () => {}); after the loader's animating property is set to true but its not
working.
Please give me any solution.
import OrientationLoadingOverlay from 'react-native-orientation-loading-overlay';
<OrientationLoadingOverlay
visible={this.state.animating}
color="#6495ed"
indicatorSize="large"
messageFontSize={16}
message="Loading..."
/>
My hardware backbutton click event listener code is as follows:
BackAndroid.addEventListener('hardwareBackPress', () => {
if(this.state.drawerState===true) {
this.refs['draw'].closeDrawer();
} else {
if(this.props.navigator.getCurrentRoutes().length===1&&
this.state.tagPressed===false){
if (stack.length===0){
Alert.alert(
'Exit',
'Are you sure?',
[
{text: 'Cancel', onPress: () => {return true;}},
{text: 'Yes', onPress: () => BackAndroid.exitApp()},
],
)
} else {
this.backButtonEvent();
}
} else {
if(this.props.navigator.getCurrentRoutes().length===1&&
this.state.tagPressed===true) {
this.setState({ animating: true });
this.setState({ tagPressed: false });
this.setState({ title: 'Repository' });
this.fetchData();
} else {
this.props.navigator.pop();
}
}
}
return true;
});
Here the stack.length is the length of array of navigated routes. And my backButtonEvent() function is as follows:
backButtonEvent() {
if(stack.length===0) {
this.refs['draw'].openDrawer();
} else{
this.setState({animating:true});
dirPath = stack.pop();
title = this.titleStack.pop();
if(stack.length===0) {
this.setState({srcUrl:require('../image/drawer1.png')});
this.setState({drawerLock:'unlocked'});
}
this.fetchData();
}
}
<ListView
dataSource={this.state.dataSource}
renderRow={(this.renderItem.bind(this))}
enableEmptySections = {true}
/>
fetchData(data){
this.setState({
dataSource: this.state.dataSource.cloneWithRows(data)
});
}
Refer to the line 82 of source code of the react-native-orientation-loading-overlay, it uses the function this.close() to close the Modal but when refer to the RN 0.41 Documentation, this.close() is not pre-defined function for Modal, therefore it triggered the mentioned error when typeof this.props.children === 'undefined'. It is a bug for the package. It might have new state to control the on/off of the Modal, and allow this.close() function to change the state to off the Modal.

How to add a disabled button to ionic 2 alert

I created an ionic2 alert and I have to disable a button according to a condition.
This is a simple structure of my code:
import { AlertController } from 'ionic-angular';
export class MyPage {
constructor(public alertCtrl: AlertController) {
}
showCheckbox(condition) {
let alert = this.alertCtrl.create();
alert.setTitle('Which planets have you visited?');
alert.addInput({
type: 'checkbox',
label: 'Alderaan',
value: 'value1',
checked: true
});
alert.addInput({
type: 'checkbox',
label: 'Bespin',
value: 'value2'
});
alert.addButton('Cancel');
alert.addButton({
text: 'Okay',
handler: data => {
console.log('Checkbox data:', data);
this.testCheckboxOpen = false;
this.testCheckboxResult = data;
}
});
alert.present();
}
}
I have to disable Okay button if given condition is true (parameter 'condition' that passed to the showCheckbox() function).
I know the question was asked over a year ago, just in case someone other needs it.
I've created a little, I would say, "workaround", which works like a charm.
alert.present() offers a Promise, so we can listen to it, after the alert was successfully created.
Now, here's what I've done:
alert.present().then(() => {
/** disable the confirm button initial */
document.querySelector('ion-alert div.alert-button-group button:nth-of-type(2)').setAttribute('disabled', 'true');
return;
});
It's a bit hacky to access the confirm button via document.querySelector(); and the above query, but the confirm button does not has a unique identifier as I've seen it, something like role="confirm" or so.
So You need to write a function, which will be triggered on each click on Your inputs (via handler).
alert.addInput({
type: 'checkbox',
label: 'testLabel',
value: 'testValue',
handler: () => {
functionToCheckConfirmButtonState();
}
});
There You need to check Your checkbox values inside the functionToCheckConfirmButtonState(); function and enable the confirm button with:
document.querySelector('ion-alert div.alert-button-group button:nth-of-type(2)').removeAttribute('disabled');
or disable it again with:
document.querySelector('ion-alert div.alert-button-group button:nth-of-type(2)').setAttribute('disabled', 'true');
Hope I could help.
Cheers
Unkn0wn0x

meteor handle form input

I'm using meteor to build a web app that shows stock information. I currently have a input on the client side which takes in text. The input is hooked up to a Lookup API by Markit on Demand. This is the code:
Template.LookupTemplate.onRendered(function() {
this.$("#Lookup")
.focus()
.autocomplete({
source: function(request,response) {
$.ajax({
url: "http://dev.markitondemand.com/api/v2/Lookup/jsonp",
dataType: "jsonp",
data: {
input: request.term
},
success: function(data) {
response( $.map(data, function(item) {
return {
label: item.Name + " (" +item.Exchange+ ")",
value: item.Symbol
}
}));
},
minLength: 0,
select: function(event,ui ) {
console.log(ui.item);
}
});
}
});
}); //Closing tag of LoookupTemplate.onRendered
How do I capture the selection by the client? When the user starts typing a company name, the jquery autocomplete kicks in and gives the client a list of options to select from. Once the user selects it and hits "enter" (submits it), the page reloads to
http://localhost:3000/Overview?stockname=AAPL
How do I capture that input (AAPL in this case) and then pass it to another function that builds a chart for that particular stock?
--Router.js
Router.configure({
// This is the default layout/top-level template
layoutTemplate: 'layout'
});
Router.map(function() {
this.route('/', {
path: '/',
action: function() {
this.redirect('landingpage')
document.title = 'Cash'
}
});
// Route for the landing page when user is not logged in
this.route('landingpage', {
path: '/landingpage',
after: function() {
document.title = 'Cash'
}
});
// Route to our main app. Note that I use / path as I treat this as default behavior
this.route('/Overview', {
path: '/Overview',
after: function () {
document.title = 'Cash';
}
});
})
IronRouter only can read the param when you define them in the router. For the case of dynamically param created by the API, the best way is using javascript to read it. Please have a look at the solution in here

Categories