I am pretty new to AngularJS and got to fix a bug in prod.
There is controller
app.controller('myCtrl', function ($scope, DatamodelUser) {
$scope.clickbutton = function (rs) {
var usr = DatamodelUser.UserAction('xyz'); //This performs some action
$scope.result = usr;
}
});
<button ng-click="clickbutton(rs)" >OK</button>
What I see is DatamodelUser.UserAction is actually invoked on a button click method works only the 1st button click after the page is loaded.. the 2nd time I click a button it does not work.
After I refresh the page again and click the button then only it works.
What I think to do is after the button is clicked I am thinking of resetting the data or refreshing DatamodelUser so that each time the user clicks the button the data loads.
any help on this is appreciated, apologies if the questions are not clear I am new to this.
Related
I have a sideMenu in my ionic project. I have a menu login. In my menu controller I have:
if (logged) {
$scope.loginText = 'Login';
}else{
$scope.loginText = 'Logout';
}
In my menu I simply add a {{loginText}} in the correct menu.
Then I do the login in another controller. When the user log in, I have to refresh the page to change the text. How can I change the text without need to refresh?
This is because the variable logged change is not detected on login. Since it is in different controller the change has to be manually send. this can be achieved by using $rootScope to send messages through different controller which are under the same parent controller. hence a message or an event has to be send. the below code will help.
in login controller after logged in.
$rootScope.$broadcast('isLOggedIn', true);
in menu controller
$scope.$on('isLOggedIn', function (event, data) {
if (data) {
$scope.loginText = 'Login';
}else{
$scope.loginText = 'Logout';
}
});
remember to inject $rootScope in login controller.
I have this application with a bunch of check boxes. Checking/un-checking these boxes will fire an $http.post() to the server. I want it to now fire 1 post as soon as the user is done clicking, but I'm not sure how to set up my $timeout.
I have a plunker set up here: https://plnkr.co/edit/QJRc9uMxJA17eFszyexO
What this currently does is that when the user checks a checkbox, a single alert is fired after 1 sec. (Im using the alert to simulate the $http.post().
Is there a way that I can reset that $timeout when the user clicks on a new check box? So if I click on 5 checkboxes continuously, it will fire 1 alert rather than 5?
$timeout() returns a promise (you can call .then() on it, but that's another story). Also there is $timeout.cancel(promise) to cancel a pending timeout. So modify your code as:
app.controller('IndexController', function($scope, $timeout) {
var prevTimeout;
$scope.onClick = function() {
if( prevTimeout ) {
$timeout.cancel(prevTimeout);
}
prevTimeout = $timeout(function() {
prevTimeout = null;
alert('some http post called.');
}, 1000);
};
$scope.model = new Array(5);
});
I think what you need is debounce functionality. If you are using lodasd check https://lodash.com/docs#debounce
I'm having trouble with a protractor test.
Overview of the test
Click button to show a form
Fill out the form
Click another button to save the form - this should call a function in one of my controllers that makes an http call and then reloads some models on the page.
When clicking the final "save" button, everything seems to freeze and the attached ng-click function never seems to get called. I don't see any errors in the console when I use browser.pause. I can see that the button is in fact clicked, but at that point, nothing seems to happen.
Final button definition:
this.addConfigFilterLineButton = element(by.css('[ng-click="cflCtrl.create();"]'));
Function that fills out the form:
this.addNewConfigFilterLine = function (cb) {
var self = this;
var deferred = protractor.promise.defer();
browser.executeScript('window.scrollTo(0,10000);')
.then(function(){
self.newConfigFilterLineButton.click();
// code that fills out the form
self.addConfigFilterLineButton.click();
browser.waitForAngular()
.then(function(){
deferred.fulfill();
});
});
return deferred.promise;
};
Spec
it('should allow creating a new ConfigFilterLine', function (done) {
var length;
settingsPage.configFilterLines.count()
.then(function(count){
length = count;
return settingsPage.addNewConfigFilterLine();
})
.then(function(){
expect(settingsPage.configFilterLines.count()).to.eventually.equal(length+1);
done();
});
});
I've tried with browser.waitForAngular and without it, and it doesn't seem to matter. When the button is clicked, nothing happens.
Any ideas would be helpful. Let me know if there's more info I can provide.
Instead of using
this.addConfigFilterLineButton = element(by.css('[ng-click="cflCtrl.create();"]'));
try something more like this:
this.addConfigFilterLineButton = element(by.id('id-of-final-button'));
My guess is that Protractor isn't correctly finding "addConfigFilterLineButton".
I need to open the menu automatically when navigate to a specific page.
but the event is ignored.
I created the menu controller:
.controller('MenuController', function ($scope, $ionicSideMenuDelegate) {
$scope.toggleLeft = function() {
$ionicSideMenuDelegate.toggleLeft();
}; })
and the specific page controller:
.controller('Sem_ConsultasCtrl', function ($scope) {
$scope.toggleLeft();
$scope.btn = function () { $scope.toggleLeft(); }
})
in my specific page i have a directive ng-click="btn()" wich works (toggles side-menu when click on button).
but if I call ' $scope.toggleLeft(); ' outside of btn() to automatically open the side menu when navigate to specific page nothing happens.
I found the problem:
when I call '$scope.toggleLeft();' outside of btn() the page/template still has not loaded/rendered the DOM. and when I click on button (btn()) works because DOM is already rendered.
to automatically open the side-menu I need to only call '$scope.toggleLeft();' when DOM is already and for achieve that I need to define a Watcher wich do something when occurs some modification to my template:
$timeout(function () {
$scope.toggleLeft();
});
$timeout(function () { //runs after DOM is render} );
This way, is working :)
EDIT:
I was going through my answers and I noticed that this answer was not correct.
calling $timeout triggers a digest cycle that captures differences in the DOM and updates it.
other events like clicking a button or writing in a input text triggers a digest cycle, thats why the changes only happened when clicked the button
I have a navbar ul in a view that shouldn't be shown if the user isn't logged in. For this I'm using ng-show="session.exists()". When the logout button (also in the nav bar view) is clicked it calls:
$scope.logout = function () {
var success = function () {
$state.transitionTo('login');
};
console.log($scope.session.exists());
Auth.logout().then(success);
console.log($scope.session.exists());
};
from my log statements i can see that the see that the session is being destroyed ok but the el elements I want hidden are still visible. The elements are hidden if I refresh the page. Am I missing a trick here? I'm new to angular and have inherited a project so any suggestions greatly appreciated!
C
Probably your function are not being fired on ngShow when you destroy the user session.
I suggest you to use a variable to control that, and set it on on your logout function.
In your controller:
$scope.loggedIn = true;
$scope.logout = function() {
$scope.loggedIn = false;
}
And in your view:
<div data-ng-show="loggedIn">Show Me!</div>
I think you are trying to update the scope variable responsible for your showing your navbar url from an asynchronous function call probably in side the success of a http call.
So try adding $scope.$digest(); just after updating the scope variable