$(this) doesn't work in angularJS - javascript

I am making a chrome extension with angularJS, now I have a problem.
I want add some button in my popup page, and I want when button is clicked, it's ancestor node disappear, here's my code.
in popup.html
<div class="deadline">
<div class="btn-group">
<button class="btn" ng-click="removeDeadline()">complete</button>
</div>
</div>
in controller.js
$scope.removeDeadline = function(){
$(this).closest(".deadline").remove();
}
I don't know why that doesn't work.
Please help me.

First, $ is a jQuery function--did you include jQuery in your extension? If not, angular.element is the function for the built-in "jQuery Lite" that AngularJS ships with.
Secondly, accessing a DOM element from inside a controller action is incorrect form when using AngularJS: Angular is all about views that automatically reflect the state of models (via the $scope). For example, the snippet you showed would be more properly written as:
<div class="deadline" ng-hide="hideLine">
<div class="btn-group">
<button class="btn" ng-click="removeDeadline()">complete</button>
</div>
</div>
$scope.removeDeadline = function(){
$scope.hideLine = true;
}
Take this quote from the FAQ to heart:
Stop trying to use jQuery to modify the DOM in controllers. Really. That includes adding elements, removing elements, retrieving their contents, showing and hiding them. Use built-in directives, or write your own where necessary, to do your DOM manipulation. See below about duplicating functionality.
If you're struggling to break the habit, consider removing jQuery from your app. Really. Angular has the $http service and powerful directives that make it almost always unnecessary. Angular's bundled jQLite has a handful of the features most commonly used in writing Angular directives, especially binding to events.

Related

Angular Web Architecture using nested components and hiding them using ng-hide

I am developing an application using Angular 1.X.
There is a component that is used across three pages.
I have several nested components into a main component. However there are two components that will only show on one page. I am currently ng-if(ing them) and was wondering if this is a bad option.
<!-- Component 1 -->
<div class="wrapper">
<div ng-if="showChildren">
<component2> </component2>
</div>
<!-- more code goes here -->
<div ng-if="showChildren">
<component3> </component3>
</div>
</div>
On the required page I would add in the controller
<component1 showChildren="true"></component1>
The code works, it gives no errors on page or in console.
Even though there might be other solutions for this, is there anything about this that is actually bad design/implementation?
This is mostly a matter of preference, as there's nothing inherently wrong with your solution.
Just a couple suggestions though:
If you are hiding all the children of the div.wrapper, why not apply the ng-show to the wrapper itself?
Since it seems that the value of showChildren won't change, why not use ng-if instead, and simplify the DOM? ng-show still generates the hidden DOM elements and uses styling to hide them, while ng-if will simply not generate them.

Why use custome directive when same thing can be done by controller in angularjs?

I am study the tutorial from code school, In the directive tutorial they are giving very simple example of custom directive like 1. Element Directive and 2. Attribute directive. So my question is we can achieve the requirement through the controller, then in which senario we will need custom directive.
Example Element directive
index.html
<product-title> </product-title>
Custom Directive
app.directive('productTitle', function(){
return {
restrict: 'E', // E for HTML Element
templateUrl: 'product-title.html'
};
});
product-title.html
<h3>
{{product.name}}
<em class="pull-right"> ${{product,price}}</em>
</h3>
Same thing can be do in controller
index.html
<div ng-controller="ctrl">
<h3> {{product.name}} </h3>
</div>
app.controller('ctrl', function(){
scope.product.name='HP';
})
Simple. Separation of concerns.
Controllers, architecturally aren't meant for HTML manipulation. They are meant for controlling data, stuff that is displayed on your view.
Whilst you are considering it simple to include that code in controller, which actually is, assume that tomorrow morning a change in the requirement forces you to alter the HTML. What follows is a heavy search and replace activity.
Directives generalize your HTML, they define a seperate layer where you can define custom tags and attributes that can simplify the view you're rendering. Stuffing everything in the controller, will slowly ugly out the whole code base, resulting in difficult code management.
By the way, I guess you'll soon stumble upon the fact that why should i use Services / Factories when i can achieve similar things using controllers. ?? You can check out this answer for more details
In this case the custom directives are mainly for the readability purposes. Custom directive allows you to wrap a chunk of HTML into a different file with a specific purpose. You could for example have a set up wizard for something on your web page. Each custom directive could then represent a separate step of your set up wizard. Instead of having a long HTML doc including all the steps.
You should always create a directive when you see a piece of code that can be reuse.. For example, a DatePicker would be created in a directive.. cause its gonna be useful in more than one place..
But even if its simple, all the logic will be at the same place and you can change it easily (only once) whenever you want. Besides, your source`ll turn more readable once you divide it in more pieces..

Restart/reload Angular app

I'm working on a project with Yii2 and Angular. The structure of the code is as follows:
<html ng-app="myApp">
<head.../>
<body>
...
<div class="body-content"> MAIN CONTENT GOES HERE </div>
...
</body>
</html>
The page contains a header and a column on the left and a center area which is rendered inside the .body-content div. Now, as you can imagine, I have some buttons in there, some other angular widgets, etc..
Yii2 has a really cool feature called renderPartial that will re-render a view file without wrapping it again in the <head> and <body>. I use that to update the content of my main area, by calling that function, getting the response with jQuery and replacing the content.
Now, that causes all buttons that where binded with Angular to stop working (I'm guessing why). My question is: How can I make Angular re-run or re-bind all my (new) DOM elements to their actions?
You would have to use the manual bootstrap way (explained in https://docs.angularjs.org/guide/bootstrap) for angular but doing that would cause a memory leak over time as angular add listener on DOM that you destroy and is not aware of it's removal, so they stay, and so does for the controller / directives / binding and other features that are referenced by your code.
Is yii2 could be wrapped into an angular directive?
I am not sure if I am getting you right - you use a frontend framework AND a backend framework to control your frontend, the latter one deliveres new DOM content you inject into your HTML?
As far as I got it, Angular is best in handling everything while getting the data (be it from the backend in JSON or other format of your choice), NOT new DOM elements.
Angular itself binds to whatever DOM nodes it is added to, handles the content and dependency injection and thus displays your data. In your case the backend PHP framework seems to hand in new DOM elements that Angular thinks of "Hey - you don't want me to be adding them? fine, then I don't." and breaks.
Maybe there are solutions for this specific case, but if I were you I would rethink the concept in terms of "Where do I want my views/templates to be rendered? What part of the whole is responsible for what?" Using two different frameworks, let alone languages, to do the same job and interfering with one another would make a mess I wouldn't want to clean up.
So if you like this Yii2 feature and want to make it work, fine - but in that case - what do you need angular for? And if you'd rather stick to Angular you just have a backend that handles data and hands it back to the frontend to do it's job with it.

Initialize ng-app after document is loaded

I'm working with AngularJS.
One of the (technical) requirements is to fetch the "ng enabled" HTML content from the server, in response to a click event, and inject it into a <div ng-app> via JavaScript.
The problem is that the newly injected HTML is not wired, as Angular goes through the compile and link phases only when the page is loaded the first time.
Is there a way to trigger them manually?
Am I approaching this problem in the wrong way? Is there a more idiomatic way to accomplish what I described?
Thanks
There are multiple ways to inject dynamic content into the view in AngularJS. One of the way to inject dynamic content is to use ng-include directive. It can take an endpoint from where to get view.
You can combine it with ng-if to achieve load view on click. For example:
<span ng-if="clicked">
<div ng-include='pathToTheHtml'></div>
</span>
The clicked variable would be false first, on clicking on the button set it to true, this would trigger ng-include to get the content and inject it into html.
If you want finer control then you need to use the $compile service. The html that needs to be injected into the DOM needs to be compiled and linked to the scope using $compile service. This can be done in a directive.
element.append($compile(htmlFragment)(scope))
angular.bootstrap(element, [modules], [config]);

When using Twitter Bootstrap is is better for performance to init plugins in JavaScript or via Data Attributes?

When using twitter bootstrap you can attach plugins in your Javascript or via data attributes. For example a modal can be made like this:
Launch demo modal
<div id="myModal">Hello</div>
Or like this:
In the HTML:
Launch demo modal
<div id="myModal">Hello</div>
In the js file:
$('.launch-modal').on('click', function() {
$('#myModal').modal('show');
});
At first I thought using data attributes would be slower since bootstrap probably scans the entire page on dom ready to see which (if any) elements are attached to what plugins, but then realized if this is the case bootstrap is doing this scanning regardless whether you attach plugins via data attributes of not in order to make the necessary check.
Is there any performance benefits of one over the other?

Categories