How to append dynamic html with dynamic data in angular1? - javascript

Basically I want to achieve like this scenario:
https://i.stack.imgur.com/LLTcK.png
My research led me to $compile, $trustAsHtml,at last directive.
In $compile and $trustAsHtml I can only append static template or only html but can't use dynamic things such ui-sref, ng-click etc.
So, I tried to create directive it is not working and also I am unable to add multiple template on click.
controller :
app.controller('Ctrl', ['$rootScope', '$scope',function ($rootScope, $scope)
{
$rootScope.enableDirective=false;
if(userHasOneApp){// checking some at least one app then only do action
$rootScope.appicon="img_url"; // data which i am passing
$rootScope.appname="App_name"; // data which i am passing
$rootScope.enableDirective=true;
}
}]);
custom directive:
app.directive('headerTemplate', function () {
return {
template:'<a ui-sref="/event" ng-click="editIt()">'
+'<img src="{{appicon}}"></a>'
+'<span>{{appname}}</span>',
scope:{
appname:'=',
appicon:'='
}
};
});
Header view :
<div> class="headerdiv">
<ul ng-if="enableDirective">
<li header-template appicon="appicon">
</li>
</ul>
</div>
Main view :
<div> class="maindiv">
<ui-view></ui-view> <!--basically I want to append template here -->
<button>Add next template</button>
</div>
Where I am doing wrong ?

Well i was facing the same issue
Check out the following link
This will surely help you.
I have implemented this and it worked in my scenario where i wanted to serve a directive when required i.e Lazy Loading of directive
https://www.codeproject.com/Articles/838402/Lazy-loading-directives-in-AngularJS-the-easy-way

Related

Angularjs loading JQuery in partial pages

I have a LAMP website that i am trying to convert to be built on MEAN and I've split the index page into partials so i could have a SPA.
I am completely new to MEAN but i'm slowly learning and trying things however i'm now stuck on JQuery slider plugin that I am using in one of my partials and it does not load any images in the placeholder when the website is ran.
I know that i am supposed to use directives so that JQuery function is loaded after the partial page is loaded into the main page and hence why nothing is being displayed where the slider should be.
This is my partial page that contains the snippet of the slider for a single image (there are 3 of these 'li' blocks at the moment for 3 images):
home.html
<div id="pm-slider" class="pm-slider">
<ul class="pm-slides-container" id="pm_slides_container">
<li data-thumb="public/app/img/home/slide1a.jpg" class="pmslide_0"><img src="public/app/img/home/slide1.jpg" alt="img01" />
<div class="pm-holder">
<div class="pm-caption">
<h1>Medical professionals</h1>
<span class="pm-caption-decription">
that you can trust
</span>
learn more <i class="fa fa-plus"></i>
</div>
</div>
</li>
</ul>
</div>
My index.html file contains div ng-view tag where all of home.html should go.
app.js contains this code for routing and I know that here should go the .directives function for the JQuery plugin
var digiProm = angular.module('digiProm', [
'ngRoute']);
digiProm.config(['$routeProvider', function($routeProvider){
$routeProvider
.when('/', {
templateUrl: 'public/app/partials/home.html'
})
.when('/services', {
templateUrl: 'public/app/partials/services.html'
})
.otherwise({
redirectTo: 'partials/home.html'
});
}]);
After watching multiple videos as well as tutorials i can't figure out how i should write my directive function to work.. I am trying to work out how to use this type of format
digiProm.directive('slider', ['$rootScope', function($rootScope) {
return {
restrict: 'EA',
templateUrl: '/path/to/template',
link: function(scope, iElement, attrs) {
//attrs references any attributes on the directive element in html
//iElement is the actual DOM element of the directive,
//so you can bind to it with jQuery
$(iElement).bxSlider({
mode: 'fade',
captions: true
});
}
};
}]);
Is the templateUrl here supposed to be the path to the jquery file for the slideshow?
What the heck would go inside the link: function(...) ?? This script has been shown as an example on how to use the bxSlider and i'm trying to use a Pulse PM-Slider so not sure what functions i'm supposed to call for it to load after the partial has been loaded...
Any kind of help is much appreciated.
Thank you in advance
If the directive is only activating on an element that already exists in another template then you don't need templateUrl.
That is used to be able to inject html into an element. in other words a directive can define it's own template
Also the restrict is to tell directive whether to look for E-an element , or A an attribute or C- a class.
I suggest you add an attribute since it makes it easier to see later on in the markup
<div slider id="pm-slider" class="pm-slider">
Then remove templateUrl from your directive declaration object.
Also note that when jQuery is included in page before angular.js iElement is already a jQuery object so you can just use iElement.bxslider({....})

Can an Angular controller bind to multiple parts of a web page?

Suppose that I've written a web page that requires the user to key in data into forms. Suppose that there are two parts of the page that are completely separate in the DOM, yet are logically related. I need to bind them to a single model.
The first (bad) solution I can think of is to completely restructure the page so that everything to be bound to the model is contained in a single <div> element (or perhaps even put the controller on the <body> element).
Another solution might be to bind the inputs to a object that could be made a member of two different controllers, but that sounds like a bit of a kludge.
Suppose the HTML looks like this:
<input ng-model='data1' />
<div>
<!-- something complicated -->
</div>
<input ng-model='data2' />
You can create a shared service and inject into both controllers. This can be achieved by either the factory or service pattern. See SO post angular.service vs angular.factory for some insight on the difference/similarity between the two.
This is the Angular way to do this. See the AngularJS services docs for more information. A simple example may include...
<div ng-app="app">
<div ng-controller="ctrlA"></div>
<div ng-controller="ctrlB"></div>
</div>
app.service('sharedService', [function () {
this.someValue = 'yo!'
}]);
app.controller('ctrlB', ['$scope', 'sharedService', function($scope, sharedService) {
console.log(sharedService.someValue) // yo!
}]);
app.controller('ctrlA', ['$scope', 'sharedService', function($scope, sharedService) {
console.log(sharedService.someValue) // yo!
}]);
JSFiddle Link

how to process html using angular and bindings (?)

here is my testing page :
<div ng-controller="test">
<input ng-keyup="asIwrite($event)" />
<p id="entityContent"></p>
</div>
and my controller :
EntitiesApp.controller('test', ['$scope', function ($scope) {
$scope.asIwrite = function ($event) {
$('#entityContent').html($event.srcElement.value);
}
}]);
this is actually working, if i write click in the input, the paragraph will hold the clickable url (processed html).
I am using jQuery to update the content of the paragraph as to show html element as they render in the page..
But using jQuery is a work-around in my opinion.
I want to achieve that using just Angular. How can I do ?
note : sure I can sweep jQuery off my project and use innerHTML of the
element but I want to know the way of doing that in Angular with
bindings. I used ng-bind on a paragraph element but that just
render the value of the textarea as is, no html process is performed.
See working example below.
You are right by doubting using jQuery is the right thing to do, and as you would expect it is not. The angular way to do that is register your input into the scope using ng-model, and the way to display it is using the ng-bind-html directive. (or simply ng-bind if it was simple text with no HTML)
However, Angular will not allow HTML binding by default as it could be a security issue. If you are sure about what you write, you can use $scope.trustAsHtml as showed in my example.
angular.module('test', [])
.controller('test', ['$scope', '$sce', function ($scope, $sce) {
$scope.trust = function(content) {
return $sce.trustAsHtml(content);
}
}]);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="test" ng-controller="test">
<input ng-model="content"/>
<p ng-bind-html="trust(content)"></p>
</div>
You probably have tried to do something like this but the content doesn't come out as html
<input ng-model="input" />
<p id="entityContent" ng-bind-html="input"></p>
You need to ensure strict context escaping as described here:
https://docs.angularjs.org/api/ng/service/$sce
Please keep in mind what you're saying you want to do is explicitly prevented by angular developers as a way to mitigate XSS attacks
You don't need to do that, angular is simplier than that.
<div ng-controller="test">
<input ng-model="variable1" />
<p id="entityContent">{{variable1}}</p>
</div>
Angular binds variables automatically. When the input's value change, the new value will be printed.

How to hide show in Angular

I am beginner in angular js
HTML
<div ng-app="myapp">
<div ng-controller="maincontrol">
<div ng-show="!vis">show</div>
<div ng-show="vis">hide</div>
</div>
<div ng-view></div>
</div>
JS
var app = angular.module('myapp', ['ngRoute'])
app.controller('maincontrol', function ($scope) {
$scope.vis = true;
$scope.fun = function () {
if ($scope.user == "home" && $scope.pass == "home") {
console.log($scope.user, $scope.pass);
$scope.vis = false;
}
}
})
app.config(function ($routeProvider) {
$routeProvider
.when('/', {
templateUrl: 'home.html'
})
.when('/contact', {
templateUrl: 'contact.html'
})
});
and also i have two html pages like
home.html
<div ng-controller="maincontrol">
<input ng-model="user"/>
<input ng-model="pass"/>
<div ng-click="fun()">
click
</div>
</div>
contact.html
<div>
contact
</div>
my expectation is after entering home into user and pass. if i click 'click' i need to show 'show' label instead of 'hide'. pls help me.
Each controller has its own scope, when you wrote $scope.vis=false on fun(), you actually created a new variable on maincontroler1 scope. If you expected this variable to affect the view which is binded to maincontroler scope, it won't happen.
I suggest 2 options:
You can use one controller for entire app (If you use same controller in two tags it will still create a new scope although it is the same controller), this way the fun() method that was called from the first view will change the boolean in the single controller and will affect the second view. Please note when you use ng-view you will have to get the variable from the parent.
So I used this code:
$parent.user
$parent.pass
Create this working plunker for you.
Share the vis boolean between 2 controllers using a service. You can
use this post for this option.
You can also use reach parent controller scope from child controller, that can be done if ng-view will be nested in the outer controller. You can use this post for option 3.

Data binding for dynamically introduced Angular controller

I am an angular beginner & trying to introduce angular in a legacy application. The page structure looks like this
<html ng-app="demoApp">
<div class="static-parent">
<div class="dyanamic" ng-controller="SimpleController">
<ul>
<li ng-repeat="cust in customers">
{{cust.name}} - {{cust.city}}
</li>
</ul>
</div>
</div>
</html>
The "dyanamic" div is added to dom when a certain button is clicked.
As this controller div is being added dynamically, i tried to load angular afterwards by calling angular bootstrap
angular.bootstrap(document,['demoApp']);
After running the above statement,
3 Li elements are getting created in the dom
But no data is being seen
on the web page. The Li elements are empty
>> angular.element(".dynamic").scope().customers; returns 3 customer objects as expected.
>> angular.element(".dynamic").scope().$apply(); did not help either.
Can you please suggest where I am going wrong? Tried other answers on stackoverflow but didn't seem to help.
Controller code:
//setting up controller
var demoApp = angular.module("demoApp", []);
var controllers = {};
controllers.SimpleController = function($scope){
$scope.customers = [{name:'dave', city:'auckland'},{name:'abe', city:'City2'}, {name:'ram', city:'City3'}];
};
demoApp.controller(controllers);
Code for adding the div dynamically:
var template = Handlebars.compile( $("#template-content-content-container").html() );
$("static-parent").html(template(data));
angular.bootstrap('.page .row', ['demoApp']);
Angular version: 1.0.6
On 1.2.28, calling angular.bootstrap(document,['demoApp']) or angular.bootstrap('.dynamic',['demoApp']);`
is giving
Error: error:btstrpd
App Already Bootstrapped with this Element
Following is the browser screenshot -
Please, check the third (accepted) answer to this: Angular bootstrapping after load of html
(direct link: Loading an AngularJS controller dynamically)
I think, you have to "compile" anything, which is added after a first 'bootstrap' call
Also, I've made this fiddle yesterday to describe my trouble, I think it fits yours.
http://jsfiddle.net/21neg0ox/
var app = angular.module('app', []);
angular.element(document).ready(function () {
angular.bootstrap(document, ['app']);
});
//c1
app.controller('c1', ['$scope', '$compile', c1Fn]);
app.controller('c2', ['$scope', '$compile', c1Fn]);
function c1Fn($scope){
$scope.isAlive = 'is alive';
}
setTimeout(wtf, 500);
function wtf(){
var myLovelyHTML = '<div ng-controller="c2">c2 {{isAlive}}</div>';
document.getElementById('c2-wrap').innerHTML = myLovelyHTML;
}

Categories