Two-way binding not working for Nested directives - AngularJS - angularjs

Scenario:
I do not want to open more than 3 chat windows on my page. Although I am able to manage that partially, what I want to achieve now is
to show USER buttons again if any chat window is closed (so that the user can again open a chat window if he closes any one of three)
Here is the working plunker . I have taken care of two-way binding
I am handling that in this link function:
link: function(scope, element, attr) {
scope.close = function (){
element.hide();
alert('scope.count not reducing the actual count on index.html')
scope.count--; // <-- THIS IS NOT DECRESING THE COUNT on main index.html
}
scope.$watch('box2', function(newIsOpenVal, oldIsOpenVal){
if(newIsOpenVal !== oldIsOpenVal){
element.find("#msg").toggle();
}
});
}

the problem in your implementation is that you are not using the count from your controller's scope, to solve it you should do :
$compile("<div chat-toggle user-name="+scope.userName+" count='count'></div>")(scope)

Related

How to write a logic when double clicking on page using angularjs

I have a page in which I have a few elements. My scenario is, when I double click on the background i.e., not clicking on any of the elements. I need to go 1 page back using angular. I am pretty new to angular. I am trying to figure out a way to implement. Any suggestions/help is appreciated.
Javascript has a native dblclick event, which is described here.
You'll need to check that the event is coming from the body itself, instead of one of the elements generating an event that then bubbles up to the body.
Try something like this, passing the body as the element:
link: function(scope, element, attrs) {
element.on('dblclick', function(e) {
if(e.target === element){
$window.history.back();
}
});
}

focus on last input ng-repeat

I have been looking at a lot of focus directives, especially those posted here.
But none seem to work for my scenario. I have a tabset and a table inside with an ng-repeat that creates rows with inputs on it. The way I create them is using ng-blur at the end of the last row checkbox so the ng-blur fires the addNewRow method. What I want is to focus the first input on the newly created row but the focus goes to the browser search bar instead.
I created a fiddle to show the problem using a directive from the first posted link.
I tested this directive:
soccerApp.directive('setfocus', function () {
return {
restrict: 'A',
link: function (scope, element, attrs) {
var focus = !! attrs.setfocus && !attrs.setfocus.replace(/true/, '');
if (focus === true) {
//alert(element);
element[0].focus();
}
}
};
});
and the element[0].focus(); actually fires when I create a new row but doesn't set the focus.
Can someone please take a look and tell me what could be wrong?
NOTE: The idea is to use the TAB key to loop through the inputs until the last one.
As Deblaton Jean-Philippe pointed out
The problem is that, at the moment you "tab" from the last input, your browser sets the focus out of the page. So you don't have any control on it anymore. I don't know if it's possible to override that without creating a fake invisible input below to keep the focus into the page
i was missing a fake input so i added a fake at the bottom after my table and it worked

Angular modal window depenging on server answer

Good day! I am rather new to angular and I need help in creating a directive or, maybe, some other solution. I have got a list of news, which are displayed one after another. It is done by ng-repeat. Inside each new there are a things like creationDate, post.media and etc. I would a new to appear in a modal window, when user clicks directly on the div with a new text. But, i would to make a request to the server after click to get the most recent version of the new.
So, this is what I want briefly:
1) User clicks on new's text.
2) The id is sent to the server.
3) Server responds with all post information
4) Some specified template loads with all information got from server and appears in a modal window.
What i tried to do:
I tried to create a directive and placed it on new's text. I created an isolated scope, which expects to have one more attribute, so I could get a postId.
scope: {
postId: '#'
}
I created a template and specified a link to it as templateURL.
Then i created a link function and inside it i created smth like this :
element.on('click', function() {
scope.postInfo = scope.findPostById(postId);
});
But for now, this directive just replaces its innerHTML :))
Some requirments:
Modal window should appear only after server receives all the information.
Thank you :)
Basically ng-repeat creates scope for every single element. So you just need to create a function i.e.
$scope.fetchNews = function(news){
newsRepository.find(news).then(function(result){
$modal.open({
templateUrl:...
controller:...
resolve:{
news:function(){
return result;
}
}
})
})
}
And in the controller of the model you inject as depenency news and after that you are done :)

AngularJS: Attempt to dynamically apply directive using ngClass causing weird functional and performance issues

Requirement
I want a textarea that expands or contracts vertically as the user types, alla Facebook comment box.
When the textarea loses focus it contracts to one line (with ellipsis if content overflows) and re-expands to the size of the entered text upon re-focus (this functionality not found on Facebook)
Note: Clicking on the textarea should preserve caret position exactly where user clicked, which precludes any dynamic swapping of div for textarea as the control receives focus
Attempted Solution
I'm already well into an AngularJS implementation, so...
Use Monospaced's Angular Elastic plugin. Nice.
Two attempts...
Attempt A: <textarea ng-focus="isFocussed=true" ng-blur="isFocussed=false" ng-class="'msd-elastic': isFocussed"></textarea> Fails because ng-class triggers no re-$compile of the element after adding the class, so Angular Elastic is never invoked
Attempt B: create a custom directive that does the needed re-$compile upon class add. I used this solution by hassassin. Fails with the following problems
Attempt B problems
Here's a JSFiddle of Attempt B Note that Angular v1.2.15 is used
I. Disappearing text
go to the fiddle
type into one textarea
blur focus on that textarea (eg click in the other textarea)
focus back on the text-containing textarea
result: text disappears! (not expected or desired)
II. Increasingly excessive looping and eventual browser meltdown
click into one textarea
click into the other one
repeat the above for as long as you can until the browser stops responding and you get CPU 100% or unresponsive script warnings.
you'll notice that it starts out OK, but gets worse the more you click
I confirmed this using: XP/Firefox v27, XP/Chrome v33, Win7/Chrome v33
My investigations so far
It seems that traverseScopesLoop in AngularJS starting at line 12012 of v1.2.15, gets out of control, looping hundreds of times. I put a console.log just under the do { // "traverse the scopes" loop line and clocked thousands of loops just clicking.
Curiously, I don't get the same problems in Angular v1.0.4. See this JSFiddle which is identical, except for Angular version
I logged this as an AngularJS bug and it was closed immediately, because I'd not shown it to be a bug in Angular per se.
Questions
Is there another way to solve this to avoid the pattern in Attempt B?
Is there a better way to implement Attempt B? There's no activity on that stackoverflow issue after hassassin offered the solution I used
Are the problems with Attempt B in my code, angular-elastic, hassassin's code, or my implementation of it all? Appreciate tips on how to debug so I can "fish for myself" in future. I've been using Chrome debug and Batarang for a half day already without much success.
Does it seem sensible to make a feature request to the AngularJS team for the pattern in Attempt A? Since you can add directives by class in Angular, and ngClass can add classes dynamically, it seems only natural to solve the problem this way.
You are severely overthinking this, and I can't think of any reason you would ever need to dynamically add / remove a directive, you could just as easily, inside the directive, check if it should do anything. All you need to do is
Use the elastic plugin you are using
Use your own directive to reset height / add ellipsis when it doesn't have focus.
So something like this will work (not pretty, but just threw it together):
http://jsfiddle.net/ss6Y5/8/
angular.module("App", ['monospaced.elastic']).directive('dynamicClass', function($compile) {
return {
scope: { ngModel: '=' },
require: "?ngModel",
link: function(scope, elt, attrs, ngModel) {
var tmpModel = false;
var origHeight = elt.css('height');
var height = elt.css('height');
var heightChangeIndex = 0;
scope.$watch('ngModel', function() {
if (elt.css('height') > origHeight && !heightChangeIndex) {
heightChangeIndex = scope.ngModel.length;
console.log(heightChangeIndex);
}
else if (elt.css('height') <= origHeight && elt.is(':focus')) {
heightChangeIndex = 0;
}
});
elt.on('blur focus', function() {
var tmp = elt.css('height');
elt.css('height', height);
height = tmp;
});
elt.on('blur', function() {
if (height > origHeight) {
tmpModel = angular.copy(scope.ngModel);
ngModel.$setViewValue(scope.ngModel.substr(0, heightChangeIndex-4) + '...');
ngModel.$render();
}
});
elt.on('focus', function() {
if (tmpModel.length) {
scope.ngModel = tmpModel;
ngModel.$setViewValue(scope.ngModel);
ngModel.$render();
tmpModel = '';
}
});
}
};
})

AngularJS $watch is called on every keypress in a text input

I have a webpage where i am building a form from dynamic json data received from server. I have developed it with KnockoutJS, a while ago. After building the form, i also have a requirement to update the form by doing an ajax request from the server, everytime a value in the form has been changed. Here is the fiddle
You see that, change event only occurs on blur (not on keypress). For example, if a text field has a value 15, and user presses backspace and then enters 5 again, that means 2 keypresses but value has not been changed. So far so good.
Problem 1
Now i am converting the code to AngularJS. I am trying to catch the change event by $watch of scope. But, it seems like watch is run everytime a keypress is happened, even though after few keypresses value is not changed. Here is the fiddle of how i am attempting. This problem is however with only text type input fields.
Problem 2
I am creating radiogroup in a manual way, e.g. if the json data is changed then we will also have to update the html as well. How can i do that in a kind of dynamic way. I was able to do that with KnockoutJS.
Problem 3
Why ng-hide is not working?
Fix for the problem 1 was to introduce a directive for blur event, following is the code of my directive:
angular.module('app', []).directive('ngModelOnblur', function () {
return {
restrict: 'A',
require: 'ngModel',
link: function (scope, elm, attr, ngModelCtrl) {
if (attr.type === 'radio' || attr.type === 'checkbox') return;
elm.unbind('input').unbind('keydown').unbind('change');
elm.bind('blur', function () {
scope.$apply(function () {
ngModelCtrl.$setViewValue(elm.val());
});
});
}
};
});
you can see the working fiddle here http://jsfiddle.net/akeelrehman/GNJtn/1/
I couldn't figure out the solution for problem 2, so i have stopped using radio inputs.
Instead of using blur, you could just use a timeout. In effect this calls your function when the user has stopped typing for X milliseconds, instead of on every keypress.
See this reply to a similar question, which has example code that does the job: https://stackoverflow.com/a/15723514/1034002

Resources