Variable passed to ng-incude in angular 1.5 component - angularjs

I tried different ways to achieve this, with no luck. I also read few post on same subjet, I don't know why I can't get this to work.
I want to use ng-include to display template content in a component. Since it's a reusable component, I'm passing the template id via bindings.
angular.module('app')
.component('detailPanel', {
templateUrl: "components/_detailPanel.html",
bindings: {
templateId: '#'
}
}
);
The component _detailPanel.html:
<div>
{{$ctrl.templateId}}
<ng-include src="$ctrl.templateId"> </ng-include>
</div>
<script type="text/ng-template" id="actionDetail.html">
THIS IS THE DETAIL
</script>
I'm passing the templateId to the component. It prints fines in the div using {{ templateId }} and this indicates the correct id is passed, but nothing is shown from ng-include. The only way I'm able to get the template to be rendered is to pass the string 'actionDetail.html' to the ng-include's src. However I'm looking to pass a variable because I want something reusable..
This example contains the ng-template directly in the component, but I intend of course to put it oustide, this was only a test.
Any thoughts would help... thanks

Related

Angularjs ng-class condition for window.location

i'm trying to unset/set a css class at a specific path url
I tried writing this code, but without any success
<div ng-class="window.location.toString().includes('ocs')? '' :'icon-home'"></div>
in chrome console i see this:
<div ng-class="window.location.toString().includes('ocs')? '' :'icon-home'" class="icon-home"></div>
I need to create a new angularjs module and scope for do this?
As you are clearing the class if location contains 'ocs', the correct approach should be this:
// in you angularjs controller:
$scope.containesOCS = window.location.toString().includes('ocs');
And in the html:
<div ng-class="{'icon-home': !containesOCS}"></div>
And if you haven't created an angular module or controller, please do so first. Without the
ng-app the angular attributes won't work.

angularjs compile json with template

I am new to angularjs, and I have an jquery background.
I want to compile json from the server into an element with an template.
What I now have for so far is:
The template:
<script type="text/ng-template" id="/tiles.html">
<div ng-repeat="tile in tiles">
{{tile.name}}<img ng-src="tile.src" />
</div>
</script>
The button for displaying the content:
<button ng-click="imageOptions.addFromList()">+ Add Image from list</button>
The function:
$scope.imageOptions.addFromList = function (){
$http
.get('/json/Tiles/get')
.success(function(data){
$scope.tiles = data;
console.log(data);
})
.error(function(data){
console.log("something did go wrong");
});
$(".prompt").html('<div ng-include src="/tiles.html"></div>');
};
The placeholder:
<div class="prompt"></div>
The placeholder will be used many times with also other content.
So I can not just type the html from the .html() argument. Like this:
<div class="prompt"><div ng-include src="/tiles.html"></div></div>
When I inspect the .prompt div it will stay uncompiled
The first thing you should do is remove jQuery library from your app while you get familiar with angular methodology.
There is no need to use html() method when all you need to do is include your template through a variety of different ways in your html source.
If the data isn't already available for ng-repeat it will simply fail quietly and do nothing. Then when the data is available it will respond automatically.
You could simply do:
<div class="prompt" ng-include src="/tiles.html"></div>
Or you could make a simple directive that will accomplish the same thing .
app.directive('prompt', function() {
return {
restrict: 'C',/* use for "class" */
templateUrl: '/tiles.html'
}
});
Simply change this
<div ng-include src="/tiles.html">
to this
<div ng-include src="'/tiles.html'">
While coding your single page application in angularjs, ideally there should not be any need for you to first get a reference to an element and then perform some action on it (You may think of this as the first step of switching from a jquery background to angularjs domain).
To achieve complete separation of model, view and controller you should just define your templates and controllers accordingly. These mappings and references should be managed by angularjs on its own.
As correctly mentioned above you should not be using .html() method of jquery. If you have included jquery in your document, it will be internally used by angularjs, but, including jquery should not be mandatory for using angularjs.
ng-repeat and ng-include also create a separate scope, so you may want to take care of those as well in future.
For your query, you may reference the template by including extra quotes in ng-include as:
<div class="prompt">
<div ng-include src="'tiles.html'"></div>
</div>
http://jsfiddle.net/PKKp8/

add a class to the ui-view based on the current state

In a AngularJS (1.2.7) project, using UI Router (0.2.8), I want to apply the current state as a class to the ui-view element, because that would allow me to apply animations for specific states, e.g. do transition A going from login to start and do transition B going from start to settings.
At the moment I have the $state object on the $rootScope (as mentioned here, which allows me to add a state-based class on the body using ng-class="$state.current.name". However, if I add that to the ui-view element, e.g.
<div ui-view ng-class="$state.current.name"></div>
Then the class is one step behind the actual state. So when going from "login" to "start", the class will be "login" instead of "start".
I think this is a bug, you can read more about the issue here:
https://github.com/angular-ui/ui-router/issues/866
Until it is fixed I suggest such a workaround:
<div ng-class="$state.current.name"><div ui-view></div></div>
I'm reading between the lines of what I think you're trying to do: you want to style a particular view differently depending on the state/route. Here's what I'm doing currently:
1) Set a state attribute on the HTML element:
<html lang="en" ng-app="MyApp" ng-controller="MyAppCtrl" state="{{ state }}">
<div ui-view="nav"></div>
<div ui-view="page" autoscroll="true"></div>
</html>
2) Update the state name whenever the route changes:
app.controller('MyAppCtrl', function($rootScope){
$rootScope.state = 'home';
$rootScope.$on('$stateChangeSuccess', function(event, toState) {
$rootScope.state = toState.name;
});
});
3) Using attribute selectors in the stylesheets:
[state="app.articles"] [ui-view="page"] {
section {
font-size: 1.8rem;
}
}
Instead of adding $state to $rootScope I just put a method on the controller of my root directive that returns the active state name. Then I added to the DOM like so:
<ui-view active-state="{{ctrl.getActiveState()}}"></ui-view>
Then in my CSS I can use selectors like this:
[active-state="someStateName"] { ... }
If you prefer a class it would be just as easy to do this:
<ui-view class="{{ctrl.getActiveState()}}"></ui-view>
...but you would want to replace all "." characters with "-" in your getActiveState() method.
but, i has question about that : <div ng-class="$state.current.name"><div ui-view></div></div>
$state.current.name equal user.login hou to code my css?

AngularJS load tabbed content directive dynamicly

I have a tabbed navigtion in my webapp that looks like this
Now I want to Change the directive each time the user clicks on one of the Navigation points. My Idea was to init the page with the first template.
$scope.currentDirective = $compile('<div order-Sale></div>');
Then when the user clicks on a tab, I wanted to change and compile the content again with a new directive in it. But for some reason this is not working. How would you proceed in order to archive this dynamic content loading? I really want to only load the content on necessary need and not just to show or hide it. I think using directives is the right way to go for it, but I'm a but stuck at the implementation... Someone any pointer ? (I don't want to use any jQuery)
What I tried [Edit]:
The controller.js
app.controller('pageController',['$scope','$compile', function($scope, $compile){
var templates = ['<div first-template></div>','<div second-template></div>'];
$scope.currentTemplate = $compile(templates[0]);
$scope.changeTemplate = function(id) {
$scope.currentTemplate = $compile(templates[id]);
};
}]);
The HTML
<div ng-controller="pageController">
<li>
<a ng-click="changeTemplate('1')">Change Template</a>
</li>
{{currentTemplate}}
</div>
UPDATE
$compile returns a linking function not a value, you cannot just bind it to your template with interpolation.
You should use ngBindHtml instead of regular bindings ( ngBind & {{ }} ).
ngBindHtml does compiling, linking and watching all out-of-the-box.
With ng-bind-html-unsafe removed, how do I inject HTML?
Here is a plunker
app.controller('pageController',['$scope','$compile','$sce', function($scope, $compile, $sce){
var templates = ['<div>first-template</div>','<div>second-template</div>'];
$scope.currentTemplate = $sce.trustAsHtml(templates[0]);
$scope.changeTemplate = function(id) {
$scope.currentTemplate = $sce.trustAsHtml(templates[id]);
};
}]);
The markup:
<div ng-controller="pageController">
<button ng-click="changeTemplate('1')">Change Template</button>
<div ng-bind-html="currentTemplate"></div>
</div>
For more robust dynamic content loading you have two good alternatives:
ngRoute from angular team.
ui-router from angular-ui team.
If you want to change and compile the content again, well that's exactly what ng-view/ ui-view directives already do for you.
Why not just use a directive:
You probably need to load a different template (html partial) for each tab.
You probably need to change the url based on the tab (and vice versa)
You probably need to instantiate a different controller for each tab.
ngRoute and ui-router come with their own directives.
You can implement your own route module if you want but that's more than just a directive.

Render string templates via ng-include

I am trying to render a piece of html, available on a dynamic route, the route is fetched via a $http.get() call, it returns a piece of html,
Just to give an example I try to load this html partial:
<h1>{{ pagetitle }}</h1>
this is a simple page example
I made a small fiddle, to mock the problem, but for the simplicity i left the http call out, and just added the html in a string on the scope.
The controller is:
function Ctrl($scope) {
$scope.data = {
view: "<h1>whaaaaa</h1>"
};
}
The page html is this:
<div ng-app="">
<div ng-controller="Ctrl">
<div ng-include src="data.view"></div>
</div>
</div>
The problem is that it does not add the string into the html file (ng-include), but it makes a http call to a url made of that string aparently.
So Is it not possible to just enter a string into an include? if not, what is the proper way to make an http call to a dynamic url, and enter the returned url into the page.
You can play with it in JSFiddle.
You can add static hooks to the template cache, so let's say you have a service that gets the template:
myApp.service('myTemplateService', ['$http', '$templateCache', function ($templateCache) {
$http(/* ... */).then(function (result) {
$templateCache.put('my-dynamic-template', result);
});
/* ... */
}]);
Then, you can do:
<div include src=" 'my-dynamic-template' "></div>
NOTE reference name must be wrapped in single quotes, this always bytes me.... NOTE
Do note that you'll have to have assigned it to the template cache before angular tries to resolve the url.
EDIT:
If the dynamic URL logic is simple enough, you can also use a conditional in the ng-include, e.g.
<div ng-include="isTrue() && 'template1.html' || 'template2.html'"
You can't do that with ng-include; reference:
ngInclude|src – {string} – angular expression evaluating to URL. If
the source is a string constant, make sure you wrap it in quotes, e.g.
src="'myPartialTemplate.html'".
Use directly ng-bind-html-unsafe like this:
<div ng-bind-html-unsafe="data.view"></div>
Demo
Creates a binding that will innerHTML the result of evaluating the
expression into the current element. The innerHTML-ed content will not
be sanitized! You should use this directive only if ngBindHtml
directive is too restrictive and when you absolutely trust the source
of the content you are binding to.
You can use ng-bind-html-unsafe
If you do not trust the html which comes from your ajax request, you can also use ng-bind-html which needs the $sanitize service to work (DEMO).
<div ng-bind-html="data.view"></div>
To use that you need to include an extra js file .
angular.module('app', ['ngSanitize']);
And of course add the app to ng-app:
<div ng-app="app">
ng-include expects a URL to an external HTML fragment, not an HTML string.
You want ng-bind-html-unsafe:
Updated demo.

Resources