Buttons not working inside $timout/ setTimeout | Angular and Ionic - javascript

I've want to display a popup, but with a bit of delay. The problem is that when I'm not delaying the popup the buttons aren't working and when I'm adding the delay the buttons don't show up! I've read online that the $timeout is an async function, but that isn't the issue, or is it?
The popup:
var myPopup = $ionicPopup.show({
templateUrl: 'templates/components/welcomePopup.html',
scope: $scope,
buttons: [{
text: 'Hejdå!',
type: 'custom-save-button',
onTap: function (e) {
$scope.showSpinner = true
}
}]
})
How I delay it:
$timeout(function (){
// Popup here
}, 3000)
But when adding a delay my buttons aren’t showing and without they delay nothing is working.
buttons: [{
text: 'Hejdå!',
type: 'custom-save-button',
Does anyone know a quick fix?
This is the code at the moment:
$timeout(function() {
var myPopup = $ionicPopup.show({
templateUrl: 'templates/components/welcomePopup.html',
scope: $scope,
buttons: [{
text: 'Hejdå!',
type: 'custom-save-button',
onTap: function (e) {
$scope.showSpinner = true
}
}]
})
}, 3000)
Thanks for reading! :)

Well I managed to solve half of the problem. I suspected that the problem had something to do with the $scope and apparently I was correct.
So I added another $scope to:
var myPopup = $ionicPopup.show({
templateUrl: 'templates/components/welcomePopup.html',
scope: $scope.$scope, // added $scope
buttons: [{
text: 'Hejdå!',
type: 'custom-save-button',
onTap: function (e) {
$scope.showSpinner = true
}
}]
})
However, the buttons aren't working yet!

Your button is not working because when you do something on your $scope in the timeout context, you're not anymore in your controller context.
The variable showSpinner should be actually set to true when you tap on the button, the problem is that Angular isn't aware that the value has changed, and therefore does not refresh the view.
To solve this, you can force a refresh by adding that piece of code after you change the value in your scope:
if ($scope.$root.$$phase !== '$apply' && $scope.$root.$$phase !== '$digest') {
$scope.$apply();
}
The condition is to prevent a refresh request while there is already one in progress.
Therefore, I don't think you need to pass a $scope inside your main $scope.
Hope this helps!

Related

How to pass ui-select2 change event to $scope.$on in angularjs?

I have a $scope.$on function which works fine when I'm leaving an unfinished operation on a tab to another:
$scope.$on("$stateChangeStart", function(event, toState) {
if (some conditions) {
event.preventDefault();
$modal.open({
templateUrl: 'prompt modal template',
controller: 'prompt modal controller',
backdrop: 'static',
size: 'sm'
})
.result.then(function (result) {
if (result === 'confirm') {
myService.doSomething(arg).then(function(result) {
$scope.doAnotherThing();
});
$state.go(toState.name);
}
else {
//stay where you were
}
});
}
});
Now I'd like to add ui-select2 change event to this function, so when user is trying to change the ui-select2 option while they have not finished the operation, the prompt modal would pop up and prevent any changes unless user confirms.
My ui-select2 ng-change="selectCity()" which it looks like:
$scope.selectCity = function() {
//some stuff
}
I tried adding $scope.selectCity/selectCity as an event after $stateChangeStart, but didn't work.
I would appreciate if someone could help me with this! Thanks

Javascript identifier for widget in Odoo

If you have two widget in a view. And you do something with the first widget and you want to update (call display_field) the second widget. How to have the identifier for the second widget?
For example in the extend definition of a widget:
local.FieldNewWidget = instance.web.form.AbstractField.extend({
init: function(parent, options) {
},
events: {
'click .oe_new_input_button': 'open_new_specific_form',
},
start: function() {
},
display_field: function() {
},
render_value: function() {
},
open_new_specific_form: function(event) {
var self = this;
var new_action = {
type: 'ir.actions.act_window',
name: $(event.target).data('name'),
res_model: $(event.target).data('data-model'),
res_id: $(event.target).data('res-id'),
view_mode: 'form',
view_type: 'form',
views: [[false, 'form']],
target: 'new',
context: {
},
flags: {'form': {'action_buttons': true}},
}
self.do_action(new_action, {
on_close: function() {
// I want to refresh (call display_field) the second widget here.
// What is the identifier for the second widget?
},
});
},
});
i think this will work but i don't know if it's the best solution. I think every widget knows witch view it's by using (this.view). why don't you use a special event to trigger it from one widget and listen for it in the other one.
For example Register an event listener on the widget to listen for property changing on the view:
//in first widget register the event listener:
this.view.on('property_name', this, this.your_method);
// in second widget trigger the event by setting the value
this.view.set('property_name', a_value);
i'm new to odoo javascript let me know if this works for you i think there is a better solution by using events triggering without changing properties at all.

Angular.JS onclick function only called on first click

I am currently working on a small aplication using Angular.JS
In my view i have following button
<md-button class="md-primary" ng-click="editUser(user, $event)">Edit</md-button>
the editUser method looks something like this:
$scope.editUser = function (user, $event) {
$scope.userToEdit = user;
$mdDialog.show({
controller: DialogController,
targetEvent: $event,
templateUrl: '/js/modules/user/views/edit.tmpl.html',
parent: angular.element(document.body),
clickOutsideToClose: true,
scope: $scope
})
.
then(function (answer) {
if (answer == "save") {
for (right in $scope.allSystemRightsStatements) {
if ($scope.allSystemRightsStatements[right].selected) {
if( $scope.userToEdit.rights==null){
$scope.userToEdit.rights = [];
}
$scope.userToEdit.rights.push($scope.allSystemRightsStatements[right]);
}
}
$scope.updateUser($scope.userToEdit);
}
$scope.userToEdit = {};
}, function () {
$scope.userToEdit = {};
});
};
$scope.updateUser = function (user) {
//userService.updateUser makes a $http PUT request
var promise = userService.updateUser(user);
promise.then(function (result) {
$mdToast.show(
$mdToast.simple(result.message)
.position($scope.getToastPosition())
.hideDelay(3000)
);
}, function (reason) {
$mdToast.show(
$mdToast.simple(reason)
.position($scope.getToastPosition())
.hideDelay(3000)
);
}, function (update) {
});
};
Now the dialog is nicely shown and the answer function is also called, everything as expected.
However, when I click the button a second time the editUser funciton is not executed. As if the onClick event from the button had been removed at dialog close.
Any help on solving this problem is greatly appreciated,
Thanks
As said here
it is probably a good idea to explicitly mention that the scope will be destroyed upon hiding the dialog (so people shouldn't pass a controller's $scope directly).
(regarding the scope you are passing to mdDialog)
So, as the scope is destroyed, angular is not binding your button with any action

ExtJS5 How to let keymap call viewController function?

I was wondering how to call a controller function from a keymaps in extjs 5?
The following code in the view is working to bind the keys to a an anonymous function, however not to a controller function. The function is also called by the button, and is working. How do I set the scope correctly that it is calling the controller function?
Ext.define("MyApp.view.users.List",{
extend: 'Ext.grid.Panel',
alias: 'widget.usersList',
controller: 'users-list',
listeners: {
scope: 'controller',
afterrender: function(window, options) {
this.keyNav = new Ext.util.KeyMap ({
target:window.el,
binding: [
{key:"s", ctrl:true, fn: function(){alert("hallo shortkey");}},
{key:"c", ctrl:true, fn: "newUserFn"},
],
scope:'controller'
});
}
},
tbar: [
{
itemId: 'users-list-btn-new',
iconCls: 'icon-add',
text: 'New User',
handler: 'newUserFn'
}
]
});
I had similar troubles with scope on key press events. I'm not using a KeyMap as you are but the event logic is still relevant.
The following assumes a controller with method "saveNewComponent" that you want to call. You must fire the view event "callSave" which is being listened to in the view to correctly forward to the controller.
Ext.define('teams.view.component.FormPanel', {
extend: 'Ext.form.Panel',
controller: "FormPanelController",
listeners: {
callSave: "saveNewComponent"
},
beforeShow: function(){
var me = this;
me.body.dom.addEventListener("keydown", Ext.bind(onKeyDown, this), false);
function onKeyDown(e) {
//Listen for Ctrl+S
if (e.ctrlKey && e.which === 83){
e.preventDefault();
me.fireEvent("callSave");
return false;
}
}
},
....
}
I tried many ways of achieving this, this this solution was the only one that had the correct context when actually inside the controller (ie this var was correct)

AngularJS and Fullcalendar: eventClick works only first time

I'm using the Angular module based on fullcalendar: https://github.com/angular-ui/ui-calendar along with the dialog module from ng-bootstrap. I configured the calendar to show a dialog for editing an event on eventClick action. It works fine only once. After closing first dialog and clicking again on any event new dialog doesn't show. But when I click on any other link on page, all desired dialogs shows one by one like they're queued somewhere some way.
Here's snippet from my controller:
$scope.showEditVisitDialog = function (event) {
var editVisitDialogOpts = {
backdropClick: false,
templateUrl: 'views/addEditVisitDialog.html',
controller: 'AddEditVisitDialogController',
resolve: {
patientId: function () {
return event.patientId;
},
visitId: function () {
return event.id;
}
}
};
var editVisitDialog = $dialog.dialog(editVisitDialogOpts);
editVisitDialog.open().then(function (updatedVisit) {
//some action
});
};
$scope.calendar = {
height: 450,
editable: true,
header: {
left: 'month agendaWeek ',
center: 'title',
right: 'today prev,next'
},
eventClick: $scope.showEditVisitDialog
};
$scope.events = [];
$scope.eventSources = [$scope.events]
Events are fetched from REST later in the controller.
In html:
<div ui-calendar="calendar" config="calendar" ng-model="eventSources"/>
No errors in console, what am I doing wrong?
Code on plunker: http://plnkr.co/edit/89sQfsU85zN4uxauFI2Y?p=preview
As always, things are simpler and more obvious when there's a fiddle/plnkr available. You need to place your call to showEditVisitDialog inside the $apply function:
...
$scope.calendar = {
editable: true,
eventClick: function(){
$scope.$apply(function(){
$scope.showEditVisitDialog()
});
}
};
...
Working plnkr.
you need to declare you fnction before uiConfig for the calendar ;)

Categories