AngularJS: Wait for ng-click event inside $scope function - javascript

All:
I have a function that is activated by an ng-click event. I want this function to wait on another ng-click event. The idea is to choose an action, and then choose a target for that action (via clickable objects in the DOM).
I'm not sure how to accomplish this. I know that I can use an Angular deferred event (using Q). However, how can I capture an ng-click event inside my original function without having to hold a reference to the deferred object within my scope?
Edit: The reason I'd like to design it this way is because I don't want my "targets" to perform any action on ng-click unless an action has been clicked; targets should only be selectable after an action has been selected.

If I understand your problem correctly, you can use the controller's $scope to keep track of this state information. E.g., in the ng-click function for an action, set a $scope.action property. In the ng-click function for the target, check that an appropriate $scope.action has been set.
If you have multiple targets, and you need to keep track an action for each one, use an array to keep track of which actions have been selected.

Related

What is the best way to handle events in AngularJS in this case?

I am absolutly new in AngularJS and I have the following doubt about how to handle event in Angular.
So I know if in a view I have something like this:
<input type="text" ng-model="handle" />
it means that exist a 2 way binding between this input element in the dom and an handle variable into the Angular $scope, for example:
$scope.handle = '';
So any change that happen into this input object implies a change of the handle property in the $scope and vice-versa.
So, into the Angular applcation, I can explicitly declare a whatcher
// I explicitly declare a whatcher on the handle property: when the value of this propertu change the function() is performed:
$scope.$watch('handle', function(newValue, oldValue) {
console.info('Changed!');
console.log('Old:' + oldValue);
console.log('New:' + newValue);
});
So it should have the same meaning of manually adding a classic vanilla JavaScript EventListener (by the addEventListener() on the object that I want to observe in a classic old vanilla JavaScript application (that don't use Angular).
When something change on the input value the function associated to the whatcher is performed.
Ok it is pretty clear for me.
Now I say that I can also do something like this.
Into the HTML code I can have something like:
<input type="button" value="Click Me" ng-click="alertClick()" />
And in the Angular controller I will have something like:
$scope.alertClick = function() {
alert("Clicked !!!");
}
So it seems like the ng-Click directive perform a function that is a $scope field when there is the click event on the button.
But can I do the same operation as done in the first example? Can I do it declaring a whatcher on the button if it is associated to a model object by the ng-model="handle" directive?
When is better use the first method and when is better the second method to handle events in AngularJS?
ngModel is used to bind an imput form the UI to your controller
ngClick is just a regular javascript expression that have access to your controller scope that will be executed at the click event.
Here you have to use ng-click.
With angular a good practice is to avoid using function like addEventListener() or Jquery other function...
Because AngularJS wrap all this functionality and will run digest loop or other voodoo magic if necessary.
Use the click event. $scope.$watch should be used watching when something changes instead of things that are better for event handlers.
The tow "methods" you pointed out are not the same thing. At all.
The first, $watch, is intended to listen to the $scope changes. You can specify which property of the scope you want to watch, and when a change occur it will call you callback function. For more details, see the Digest cycle documentation.
The second, ng-click attribute directive, listen to the DOM events and evaluate the expression you pass in when the event occur.
In your case, for the button, you have two options. You can use the ng-click attribute directive to trigger a function in your scope OR use the ng-submit attribute directive in the form html tag of your inputs. That way you can trigger the form validation with the button or when the Enter is pressed.
See the documentation for ngSubmit.
ngModel applies to specific elements such as input,select, and textarea. As the result, you cannot use ngModel on a button. That is why you use ngClick to get the click event.

angular ngClass evaluation

I've been learning AngularJs and have built a very basic Angular app. In one part of the app, I've used ngClass at a div element like
<div ng-class='{"some class": aFuncTruthyOrFalsy()}'>
<!-- aFuncTruthyOrFalsy() is defined in the controller for this view-->
Now, there's an input element in the view that is non-related to the above element and does not relate at all to any of the values checked in the function above.
I noticed that every whenever I type something in the input field (change event, keypressed event) it causes a re-evaluation of the ngClass. (I've put in a console log inside the aFuncTruthyOrFalsy function). I'm not able to determine which all events are bubbling to cause the reevaluation.
It seems to me that ngClass reevaluates at every single event in the page.
Can anyone please explain/elaborate this behavior?
Is it possible to cache the evaluated class at the initial load of the view?
What if there are multiple ngClass being used in the same view and each of the expression evaluation is delegated to some function that again does some multiple operation to come to get the evaluated expression?
Angular binding is using $watch to monitor changes in the function value. The digest cycle is calling your function to compare the result with last value.
This article is nice explaining this
http://tutorials.jenkov.com/angularjs/watch-digest-apply.html#watch
I suggest binding to scope variables instead of functions. i.e. have a variable in the scope that will store result of that function, and you update that whenever required.
after all you don't want to call methods from your view probably.Your current setup leaves the door open to make the whole MVC concept void,e.g. someone later add functionality inside that method that was supposed to be just a getter.
When something is changed in the scope AngularJS automatically triggers a $digest cycle by calling $digest(). When the $digest cycle starts, it fires each of the watchers.
Angular sets up a watcher on the scope model, which in turn updates the view whenever the model changes.
So when you change something in the scope, all the watchers are fired and the model is reevaluated.
Here is a good article on the topic: Link
You can do something like
<div ng-class="{'background1': color.back}">
<label> <span>{{emp.comp}}</span> </label>
</div>

ID of button changes, but document.ready function calls previous value's method

I'm writing a simple single page application with Express.js. At the bottom of the page is a form, and this form is used to add users to a table, or to update a specific user. The 'submit' button will have a different function depending on the ID of the button at the time it is pressed.
Inside my document.ready function, I have 2 lines of interest:
$('#btnAddUser').on('click', addUser);
$('#btnUpdateUser').on('click', updateUser);
I also have methods that change the value of this id from #btnAddUser to #btnUpdateUser, and vice versa. I can get the ID to change. The issue is that the document.ready function doesn't seem to consider these changes.
For instance, the app starts out with the id #btnAddUser. Then I change it to have the Id #updateUser, and I can see that this works. When I press the button, though, the addUser method fires instead of the updateUser method, and I'm not sure why.
Pointy's answer should work, but this is an X->Y problem. You shouldn't be trying to toggle functionality by changing an element's ID.
Instead, store a value somewhere that says what the button should do, and then use that. You could use a data-* attribute on the button if you want:
<!-- Dynamically change data-action and value as needed -->
<input id="btnUserAction" type="button" data-action="add" value="Add" />
$('#btnUserAction').on('click', function (e) {
var action = ($(this).data("action") === "add") ? addUser : updateUser;
action.call(this, e);
});
Alternatively, you could have two separate buttons and show/hide them. Either approach should work.
You can get the effect you want by using event delegation to set up the handlers:
$(document).on('click', '#btnAddUser', addUser);
$(document).on('click', '#btnUpdateUser', updateUser);
By doing it that way, you defer the inspection of the element until the time a "click" actually happens. With your code, the elements were located at the time the handlers were assigned. After that, it doesn't matter what the "id" value is because the handler is directly associated with the DOM node (via an internal map that jQuery maintains).
This won't work, because the click event is assigned one time when ready function executes. I think the better way is to have two buttons and show/hide them instead of changing the id.
Another way would be to store the action you want in an attribute:
$('#mybutton').click(function() {
var action = $(this).attr("data-action");
if(action == "do_this")
// ...
});
And for changing the action:
$('#mybutton').attr("data-action", "do_this");

Which event used in jquery when textbox value get changed using code not by manually?

I am developing a application in MVC.
I have a view which contain another partial view.
I have textbox1 in a parent view but its value get assigned from partial view.
Now, the moment the Textbox1 get assigned with some value, I want to perform some action
like put the 10% value textbox1 value on the another textbox, textbox2 of the view.
( I want the event when textbox value get changed by code, not the manual entry.
so cant use blur() event. )
which event in jquery should I used to perform this task ?
Partials views are all processed server-side, where Javascript is not executed. Javascript only works with the full page and does not know anything about partials, so take this worry out of your question.
As already been mentioned, you need .change() and if that is not good enough, just create a function that updates value of your checkbox and do other stuff which you need doing.
//psudo-code using .trigger()
function updateTextbox(value){
$('#myTexboxId').val(value);
$('#myTexboxId').trigger('change');
}
And here another method where you create another function that updates your values and does the calculation for you.
//pseudo-code using another function
function updateMyTextbox(value){
$('#myTextboxId').val(value);
doCalculation();
}
$('#myTextBoxId').on('change',function(){
doCalculation();
});
function doCalculation(){
// update your other values
}

Referencing and calling a method in JavaScript

I have some JavaScript/jQuery code that watches for the "changed" event on a checkbox:
$(control).change(function() {
alert("changed to: " + $(this).is(":checked"));
});
This works fine.
I'd like to create a reference to the change() function on the particular object, and call it indirectly, like so:
var onSomeChange = $(control).change;
onSomeChange(function() {
alert("changed to: " + $(this).is(":checked"));
});
I need to call it indirectly because I'll want to switch the method I'm assigning to onSomeChange with a different one, depending on the circumstances. (The single assignment to onSomeChange is just here for illustration).
This doesn't work. In Firebug I get this error:
this.bind is not a function
How can I get a reference to an object's method and call it without calling it from the object directly?
Background
The context may be significant; if there's an entirely different way to do what I want, that's fine too.
The behavior of the change event in JavaScript is a bit different for check boxes and radio buttons. A check box fires change whenever its state changes (checked or unchecked). However, radio buttons (in Firefox at least; I think it's even more complicated in other browsers) only fire a change for the radio button group as a whole. That's understandable, but I want to bind different actions to the states of the individual radio buttons. (Specifically, I want to potentially hide or show certain divs depending on the radio button states).
I think I can handle the event discrepancies by binding a custom event to each radio and then triggering it based on a change in the group. So I have extended jQuery to add a radioChange() method. This method
Now, I'd like to swap out this code with something that calls a different event-handling method depending on the type of the control. (Aside: it's because radio button seem to be handled differently than check boxes, so I have a different radio-button-specific event). I've added a radioChanged() extension method to jQuery to support this.
Now I want to have a method that registers a listener to either changed() or radioChanged() depending on the type of the object. Determining that is easy:
var change = $(control).is(":radio") ? $(control).radioChange : $(control).change;
The problem is that I can't actually call the method at the change reference without generating the error above.
Is there something else I should be doing to make this work?
Answer to original question:
You need to apply it on a object which has bind as prototype. probably enough to just pass $(control) as object in question, or perhaps $ is enough.
var $control = $(control);
var change = $control.change;
change.call( $control,
function() {
alert("changed to: " + $(this).is(":checked"));
}
);
sounds like you just need to call the bind event and pass it the targeted event string
$(control).bind($(control).is(":radio") ? "radioChange", "change", function () {});

Categories