Repeat Content with different NG-Includes - AngularJS - angularjs

I have two divs on a page, outer and inner. The outer one has same styling everywhere on the page, so I would like to repeat it using ng-repeat (what actually works fine). The inner one should contain different content, which I would like to insert from different html templates using ng-include directive. The code I wrote does not show me any error messages, however does not work. Could you please see what I am doing wrong? Thanks.
<html lang="en" ng-app="myApp">
<body ng-controller="myCtrl as ctrl">
<div id="outer" ng-repeat="tpl in ctrl.templates">
<div id="inner" ng-include="tpl.templates">
</div>
</div>
<script>
var app = angular.module('myApp', [])
.controller('myCtrl', [function() {
var self = this;
self.templates = [
{template: 'template.htm'},
{template: 'template2.htm'},
{template: 'template3.htm'},
{template: 'template4.htm'}
]
}]);
</script>
</body>
</html>

I don't really know if it is right but i guess there is an error in
ng-include="tpl.templates"
I think it should be :
ng-include="tpl.template"
(removed "s" from templates)

Related

Lose the focus after inserting a letter

I have written a script which represent a json data in 2 ways: JSBin
<!DOCTYPE html>
<html>
<head>
<script src="https://handsontable.github.io/ngHandsontable/node_modules/angular/angular.js"></script>
</head>
<body ng-app="app">
<div ng-controller="Ctrl">
GUI:
<div ng-repeat="item in data">
<input ng-model="item.val">
</div>
<br><br><br>
Textarea:<br>
<textarea rows=10 cols=20 ng-model="dataString"></textarea>
</div>
<script>
var app = angular.module('app', []);
app.controller('Ctrl', ['$scope', '$filter', function($scope, $filter) {
$scope.data = [{val: "1"}, {val: "2"}];
$scope.$watch('data', function(data_new) {
$scope.dataString = $filter('json')(data_new);
}, true);
$scope.$watch('dataString', function(dataString_new) {
$scope.data = JSON.parse(dataString_new);
}, true);
}]);
</script>
</body>
</html>
Thus, modifying the value in GUI will change the string in the textarea (because of $watch('data'); and modifying the string in the textarea will change the GUI (because of $watch('dataString')).
However, the problem is that when we change the value in GUI, we lose the focus after inserting a letter.
Does anyone know how to amend this?
So the problem is that you are iterating over an array (ng-repeat) and changeing the items of the array. The items are removed from the DOM and new one are inserted because they are strings and thereby compared by value. This makes you loose focus.
It's pretty simple to fix though. Just track by index as the objects are in identical order.
Change:
<div ng-repeat="item in data">
To:
<div ng-repeat="item in data track by $index">

Angular 1.5 - Component() Method

I'm trying to get the component method working which is new for Angular 1.5. So far I acheived the following see my jsFiddle JSFIDDLE. For some reason I can not get the templateUrl working so that I can see the html template with the defined scope. Any help would be great.
JSFIDDLE
JS
var app = angular.module('myApp', []);
app.controller('mainCtrl', function($scope) {
$scope.name = "Tony Danza";
});
app.component("myBox", {
bindings: {},
controller: function($element) {
var myBox = this;
myBox.game = 'World Of warcraft';
},
controllerAs: 'myBox',
templateUrl: "/template",
transclude: true
})
HTML
<div ng-app="myApp" ng-controller="mainCtrl">
<script type="text/ng-template" id="/template">
<div style='width:40%;border:2px solid black;background-color:yellow'>
Your Favourite game is: {{myBox.game}}
</div>
</script>
Hi {{name}}
<div my-box>
</div my-box>
</div><!--end app-->
Angular components must be elements. Use <my-box> instead of <div my-box>.
The documentation on Components doesn't make this immediately clear, but it is documented.
when you want a directive that is triggered by an attribute or CSS class, rather than an element
The directive/component comparison table also explains that restrict is unavailable for components and they are always elements.

Angularjs href attribute remove if value is mailto:email

I need to show link in page having attribute value mailto.
normal href attribute value working fine but if value is email than it removed
Code:
myCtrl.link = '<code>Email</code>';
<code><span ng-bind-html="myCtrl.link"></span></code>
rendered output:
<code><a target="_blank">Email</a></code>
Please suggest how to handle anchor having href value like mailto:sulok#atlogys.com
You are running into a "security" issue,
please have a look at this doc-page...
Just say "this is safe" to angular:
function TestCtrl(vm, $sce) {
'use strict';
var htmlString = '<code>Email</code>';
vm.link = $sce.trustAsHtml(htmlString);
}
angular
.module('test', [])
.controller('TestCtrl', ['$scope', '$sce', TestCtrl])
;
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<article ng-app="test">
<div ng-controller="TestCtrl">
<code><span ng-bind="link"></span></code>
</div>
</article>

How to organize my first angularJS simple project?

My goal is to create a SPA using AngularJS.
I know concepts of AngularJS, however I lack experience with planning the whole project, since I have never created a real project with it.
The template is quite simple: there is a nav header at the top (that switch either user is loggedon or not) and the content of the site.
The header has 2 views (depending if user is loggedon or not) and container has many views (photo gallery, video gallery etc...)
There may be also a simple footer, working the same way as header.
1) Should I use 1 global controler for whole site or have a headerController and containerController ?
2) Have would these 2 controllers communicate ? (ex: header controller stores the username and password of a loggedon user) ?
Maybe someone could provide a simple stub of AngularJS arhcitecture for such a website ?
Regards
You can (and should) use a "global" controller, controlling the top level view and scope, and others controllers can control each component that have its own behavior.
<!DOCTYPE html>
<html data-ng-app="myapp">
<head>
<!-- ... -->
</head>
<body data-ng-controller="BodyCtrl">
<section id="navbar" data-ng-controller="NavbarCtrl">
<!-- ... -->
</section>
<section id="content" data-ng-controller="ContentCtrl">
<div data-ng-controller="FirtSubCtrl">
<!-- ... -->
</div>
<div data-ng-controller="SecondSubCtrl">
<!-- ... -->
</div>
</section>
</body>
</html>
Controllers can communicate between themselves using events, but it should be used in restricted situations. Instead, you should write some services (or factory, value, provider) to encapsulate the shared logic in your app (and shared objects). Then you can inject any service in each controller that need it.
angular.module('myapp',[]) // define the myapp module
.factory('myService', ['', function(){ // define a service to share objects and methods
var _myLogic = function(){
// ...
return ret;
};
var _myObject = {
prop1: "my first prop value",
prop2: "my second prop value"
};
return {
myLogic: _myLogic,
myObject: _myObject
};
}])
.controller('BodyCtrl', ['$scope', 'myService', function($scope, myService){
$scope.myScopeMethod = myService.myLogic;
$scope.myObject = myService.myObject;
}])
.controller('FirtSubCtrl', ['$scope', 'myService', function($scope, myService){
$scope.myScopeMethod = myService.myLogic;
$scope.myObject = myService.myObject;
}])
;
Here you can notice that two controllers can share the exact (or not) object or method, injecting the shared services.
Dealing with ng-view means dealing with templates :
Here you index :
<!-- index.html -->
<!DOCTYPE html>
<html data-ng-app="myapp">
<head>
<!-- ... -->
</head>
<body data-ng-controller="BodyCtrl">
<section id="navbar" data-ng-controller="NavbarCtrl">
<!-- ... -->
</section>
<ng-view></ng-view>
</body>
</html>
And your views :
<!-- template/contentIfLogged.html -->
<section id="contentIfLogged" data-ng-controller="ContentCtrl">
<div data-ng-controller="FirtSubCtrl">
<!-- ... -->
</div>
<div data-ng-controller="SecondSubCtrl">
<!-- ... -->
</div>
</section>
and
<!-- template/contentIfNOTLogged.html -->
<section id="contentIfNOTLogged" data-ng-controller="Content2Ctrl">
<div data-ng-controller="ThirdSubCtrl">
<!-- ... -->
</div>
<div data-ng-controller="FourthSubCtrl">
<!-- ... -->
</div>
</section>
Now, you have to configure your routes to enable the correct view, onevent or button click.
angular.module('myapp').config(function($routeProvider){
$routeProvider
.when('/notlogged',
{templateUrl: 'template/contentIfLogged.html'}
)
.when('/logged',
{templateUrl: 'template/contentIfNOTLogged.html'}
)
.otherwise({redirectTo: '/notlogged'})
});
Now, in your <section id="nav"> element, you can add these buttons :
<section id="navbar" data-ng-controller="NavbarCtrl">
<a class="btn" href="#logged">
Logged view
</a>
<a class="btn" href="#notlogged">
Not logged view
</a>
</section>
and then, switch between your view clicking it.
Or, programmaticaly, in your controller (or in a service), you can switch using the $location angular service :
.controller('NavbarCtrl', ['$scope', '$location', 'myService', function($scope, $location, myService){
$scope.myScopeMethod = myService.myLogic;
$scope.myObject = myService.myObject;
var login = function(){
$location.path('/logged');
};
var logout = function(){
$location.path('/notlogged');
};
}])
To you to fill the gaps to fit your application, but the base organization of your simple app is there.

How/when to use ng-click to call a route?

Suppose you are using routes:
// bootstrap
myApp.config(['$routeProvider', '$locationProvider', function ($routeProvider, $locationProvider) {
$routeProvider.when('/home', {
templateUrl: 'partials/home.html',
controller: 'HomeCtrl'
});
$routeProvider.when('/about', {
templateUrl: 'partials/about.html',
controller: 'AboutCtrl'
});
...
And in your html, you want to navigate to the about page when a button is clicked. One way would be
<a href="#/about">
... but it seems ng-click would be useful here too.
Is that assumption correct? That ng-click be used instead of anchor?
If so, how would that work? IE:
<div ng-click="/about">
Routes monitor the $location service and respond to changes in URL (typically through the hash). To "activate" a route, you simply change the URL. The easiest way to do that is with anchor tags.
Go Home
Go to About
Nothing more complicated is needed. If, however, you must do this from code, the proper way is by using the $location service:
$scope.go = function ( path ) {
$location.path( path );
};
Which, for example, a button could trigger:
<button ng-click="go('/home')"></button>
Here's a great tip that nobody mentioned. In the controller that the function is within, you need to include the location provider:
app.controller('SlideController', ['$scope', '$location',function($scope, $location){
$scope.goNext = function (hash) {
$location.path(hash);
}
;]);
<!--the code to call it from within the partial:---> <div ng-click='goNext("/page2")'>next page</div>
Using a custom attribute (implemented with a directive) is perhaps the cleanest way. Here's my version, based on #Josh and #sean's suggestions.
angular.module('mymodule', [])
// Click to navigate
// similar to <a href="#/partial"> but hash is not required,
// e.g. <div click-link="/partial">
.directive('clickLink', ['$location', function($location) {
return {
link: function(scope, element, attrs) {
element.on('click', function() {
scope.$apply(function() {
$location.path(attrs.clickLink);
});
});
}
}
}]);
It has some useful features, but I'm new to Angular so there's probably room for improvement.
Remember that if you use ng-click for routing you will not be able to right-click the element and choose 'open in new tab' or ctrl clicking the link. I try to use ng-href when in comes to navigation. ng-click is better to use on buttons for operations or visual effects like collapse.
But
About
I would not recommend. If you change the route you might need to change in a lot of placed in the application. Have a method returning the link. ex:
About. This method you place in a utility
I used ng-click directive to call a function, while requesting route templateUrl, to decide which <div> has to be show or hide inside route templateUrl page or for different scenarios.
AngularJS 1.6.9
Lets see an example, when in routing page, I need either the add <div> or the edit <div>, which I control using the parent controller models $scope.addProduct and $scope.editProduct boolean.
RoutingTesting.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Testing</title>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular-route.min.js"></script>
<script>
var app = angular.module("MyApp", ["ngRoute"]);
app.config(function($routeProvider){
$routeProvider
.when("/TestingPage", {
templateUrl: "TestingPage.html"
});
});
app.controller("HomeController", function($scope, $location){
$scope.init = function(){
$scope.addProduct = false;
$scope.editProduct = false;
}
$scope.productOperation = function(operationType, productId){
$scope.addProduct = false;
$scope.editProduct = false;
if(operationType === "add"){
$scope.addProduct = true;
console.log("Add productOperation requested...");
}else if(operationType === "edit"){
$scope.editProduct = true;
console.log("Edit productOperation requested : " + productId);
}
//*************** VERY IMPORTANT NOTE ***************
//comment this $location.path("..."); line, when using <a> anchor tags,
//only useful when <a> below given are commented, and using <input> controls
$location.path("TestingPage");
};
});
</script>
</head>
<body ng-app="MyApp" ng-controller="HomeController">
<div ng-init="init()">
<!-- Either use <a>anchor tag or input type=button -->
<!--Add Product-->
<!--<br><br>-->
<!--Edit Product-->
<input type="button" ng-click="productOperation('add', -1)" value="Add Product"/>
<br><br>
<input type="button" ng-click="productOperation('edit', 10)" value="Edit Product"/>
<pre>addProduct : {{addProduct}}</pre>
<pre>editProduct : {{editProduct}}</pre>
<ng-view></ng-view>
</div>
</body>
</html>
TestingPage.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<style>
.productOperation{
position:fixed;
top: 50%;
left: 50%;
width:30em;
height:18em;
margin-left: -15em; /*set to a negative number 1/2 of your width*/
margin-top: -9em; /*set to a negative number 1/2 of your height*/
border: 1px solid #ccc;
background: yellow;
}
</style>
</head>
<body>
<div class="productOperation" >
<div ng-show="addProduct">
<h2 >Add Product enabled</h2>
</div>
<div ng-show="editProduct">
<h2>Edit Product enabled</h2>
</div>
</div>
</body>
</html>
both pages -
RoutingTesting.html(parent), TestingPage.html(routing page) are in the same directory,
Hope this will help someone.
Another solution but without using ng-click which still works even for other tags than <a>:
<tr [routerLink]="['/about']">
This way you can also pass parameters to your route: https://stackoverflow.com/a/40045556/838494
(This is my first day with angular. Gentle feedback is welcome)
You can use:
<a ng-href="#/about">About</a>
If you want some dynamic variable inside href you can do like this way:
<a ng-href="{{link + 123}}">Link to 123</a>
Where link is Angular scope variable.
just do it as follows
in your html write:
<button ng-click="going()">goto</button>
And in your controller, add $state as follows:
.controller('homeCTRL', function($scope, **$state**) {
$scope.going = function(){
$state.go('your route');
}
})

Resources