I am quite new to angular.
I am trying to manage a list of contacts to be able to select one to display some details on the side. I was able to do it without directives but then I wanted to use directives and be able to show which one is selected in the list.
With directives I am able to display the list but when I select a contact it doesn't show details anymore so the select is not working and I can't get it to work as those directives are making me crazy.
Here is contact.html:
<li><a href selected="selected" ng-click='selectContact(contact)' ng-transclude></a></li>
// Code goes here
var app = angular.module("contactList", []);
app.service("peopleService", function($http) {
this.getPeople = function() {
return $http.get('people.json');
};
});
app.controller("peopleController", function($scope, peopleService) {
$scope.selectedContact = {};
$scope.selectedContactImage = ""
$scope.showDetail = false;
peopleService.getPeople().then(function(response) {
$scope.people = response.data.People;
});
$scope.selectContact = function(contact) {
$scope.selectedContact = contact;
if (contact.img) {
$scope.selectedContactImage = contact.img;
}
$scope.showDetail = true;
};
});
app.directive("contactList", function(){
return{
restrict: 'EA',
replace: true,
transclude: true,
template: "<div ng-transclude></div>",
controller: function(){
this.gotOpened = function(selectedContact){
contacts.forEach(function(contact){
if(selectedContact != contact){
contact.selected = false;
}
});
};
}
};
});
app.directive("contact", function(){
return {
restrict: 'EA',
replace: true,
transclude: true,
require: '^?contactList',
scope: {selected: '='},
templateUrl: 'contact.html',
link: function(scope, element, attrs, contactListController){
scope.selected = false;
scope.selectContact = function selectContact(){
scope.selected = !scope.selected;
contactListController.gotOpened(scope);
};
}
};
});
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" href="style.css" />
<script data-require="angularjs#1.6.4" data-semver="1.6.4" src="https://code.angularjs.org/1.6.4/angular.min.js"></script>
<script src="script.js"></script>
</head>
<body ng-app="contactList">
<div ng-controller="peopleController">
<contact-list>
<contact class="contact" ng-repeat="contact in people">
{{contact.name}}
</contact>
</contact-list>
<div class="list">
<ul>
<li ng-repeat="p in people">
<a href ng-click='selectContact(p)'>{{p.name}}</a>
</li>
</ul>
</div>
<div class="detail" ng-show="showDetail">
<div class="detailimagewrapper">
<img class="detailimage" src="{{selectedContactImage}}">
</div>
<label>Rating</label>
<p>{{selectedContact.rating}}</p>
<label>Description</label>
<p>{{selectedContact.Description}}</p>
</div>
</div>
</body>
</html>
Looks like you are using transclude and replace here. I expect this is causing your anchor tag to be replaced by the content which your contact directive is wrapping. Try removing the ng-transclude attribute from the anchor tag and instead adding <ng-transclude></ng-transclude> within the anchor tag.
contact.html would become:
<li>
<a href selected="selected" ng-click='selectContact(contact)'>
<ng-transclude></ng-transclude>
</a>
</li>
Related
I have the following code in my directive:
testModule.directive('TestOne',function(){
return{
replace: true,
controller: 'TestCtrl',
link: function(scope, element, attrs){
element.on('click', function(e) {
//my own code is there
});
}
}
}
I wanted to call the above click function on ng-click with the below event in html(ng-click="mytest()"). How can I call or write exactly so that I can execute my function requirements in the above directive's element click function as per my requirements.
html:
<div test-one ng-repeat="items in testjson">
<div class="title">{{items.name}}</div>
<div class="context-menu">
<ul>
<li ng-click="mytest()">TestFunction</li>
</ul>
</div>
</div>
Thanks in advance.
First make the first letter of the directive simple
directive('TestOne',function(){
to
directive('testOne',function(){
Then create a scope function for ng-click inside the link function
.directive('testOne',function(){
return{
restrict : 'A',
replace: true,
link: function(scope, element, attrs){
scope.mytest = function() {
console.log("working")
}
}
}
})
Demo
angular.module("app",[])
.controller("ctrl",function($scope){
$scope.testjson = [{"name":"sss"},{"name":"ssss"}]
}).directive('testOne',function(){
return{
restrict : 'A',
replace: true,
link: function(scope, element, attrs){
scope.mytest = function() {
console.log("working")
}
}
}
})
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="app" ng-controller="ctrl">
<div test-one ng-repeat="items in testjson">
<div class="title">{{items.name}}</div>
<div class="context-menu">
<ul>
<li ng-click="mytest()">TestFunction</li>
</ul>
</div>
</div>
</div>
I want an angular diretive to add an inner wrapper to a DOM element. Unfortunately it's not wrapping but replacing the inner part of the element. (see plunker)
So I have this html snippet:
<body ng-app="plunker">
<div class="outer" wrapp-my-content>
<label>Name: </label>
<input type="text" ng-model="name" />
<p>Hello {{name}}</p>
</div>
</body>
The directive should change this into
<body ng-app="plunker">
<div class="outer" wrapp-my-content>
<div class="inner-wrapper">
<label>Name: </label>
<input type="text" ng-model="name" />
<p>Hello {{name}}</p>
</div>
</div>
</body>
But what I get is
<body ng-app="plunker">
<div class="outer" wrapp-my-content>
<div class="inner-wrapper">
</div>
</div>
</body>
Directive Code:
var app = angular.module('plunker', []);
app.directive('wrappMyContent', function() {
return {
restrict: 'A',
transclude: true,
replace: true,
link: function(scope, element) {
var innerWrapper = angular.element('<div class="inner-wrapper" ng-transclude></div>');
element.prepend(innerWrapper);
}
}
});
How can I fix that?
You've mixed up ng-transclude and custom transclude by link:
1. Use template of directive (demo):
var app = angular.module('plunker', []);
//Recommended angular-way
app.directive('wrappMyContent', function() {
return {
restrict: 'A',
transclude: true,
template:'<div class="inner-wrapper" ng-transclude></div>',
link: function(scope, element) {
}
}
});
2. Do transclude by custom link (demo) :
var app = angular.module('plunker', []);
//Equals transclude by your self
app.directive('wrappMyContent', function($compile) {
return {
restrict: 'A',
scope:true,
link: function(scope, element) {
var innerContent = element.html();
var innerWrapper = angular.element('<div class="inner-wrapper"></div>').append(innerContent);
//Do compile work here.
$compile(innerWrapper)(scope.$parent)
element.empty().append(innerWrapper);
}
}
});
Use a template for your '<div class="inner-wrapper" ng-transclude>' part instead of just making an element and prepending it... the ng-transclude directive won't be processed unless it's compiled which the template will be.
I hava a directive already(appView) and that has some html to load through templateUrl. As of now, I need to add one more custom directive to the template that is being used by another directive(appView).
Please see my code below and it is not working as expected. Any help on this how i can make this work please?
View.html (template)
<div>
<div class="dragdrop" id="dropzone" dropzone> //here is my custom directive
<div class="fileUpload btn btn-primary">
<span>UPLOAD ASSETS</span>
<input id="dzFile" type="file" class="upload" />
</div>
</div>
</div>
angular js
var appModule = angular.module("Newapp", []);
appModule.directive("appView", appView);
function appView(){
var directive = {
restrict: 'E',
templateUrl: 'app/View.html'
};
return directive;
}
appModule.directive("dropzone", function(){ //This is added to the View.html as attribute(see above html code with **)
var directive = {
restrict: 'A',
link: FullDragDrop
};
return directive;
});
function FullDragDrop(){
console.log("soemthing goes here");
}
How can I make this possible Please?
This code works for me.
Make sure templateUrl: 'app/View.html' exists
<script>
var appModule = angular.module("Newapp", []);
appModule.directive("appView", appView);
function appView(){
var directive = {
restrict: 'E',
templateUrl: 'view.html'
};
return directive;
}
appModule.directive("dropzone", function(){ //This is added to the View.html as attribute(see above html code with **)
var directive = {
restrict: 'A',
link: FullDragDrop
};
return directive;
});
function FullDragDrop(){
console.log("soemthing goes here");
}
</script>
<script type="text/ng-template" id="view.html">
<div class="dragdrop" id="dropzone" dropzone> //here is my custom directive
<div class="fileUpload btn btn-primary">
<span>UPLOAD ASSETS</span>
<input id="dzFile" type="file" class="upload" />
</div>
</div>
</script>
<body>
<app-view></app-view>
</body>
I have developed a transclude directive and I set it to use angularjs template script everything works fine but I still cannot access the bind data.
My code:
index.html
<div side-element="box" title="Links">
<ul>
<li>Link 1</li>
<li>Link 2</li>
</ul>
</div>
<script id="box" type="text/ng-template">
<div class="side-box">
<div class="content">
<h2 class="header">Box {{ title }}</h2>
<span class="content" ng-transclude></span>
</div>
</div>
</script>
<script id="ad" type="text/ng-template">
<div class="side-ad">
<div class="content">
<h2 class="header">AD {{ title }}</h2>
<span class="content" ng-transclude></span>
</div>
</div>
</script>
app.js:
angular.module('myApp.directives')
.directive('sideElement', function ($templateCache, $log) {
return {
scope: {
title: '#'
},
transclude: 'element',
link: function(scope, element, attrs, ctrl, transclude){
var template = $templateCache.get(attrs.sideElement);
var templateElement = angular.element(template);
$log.info(scope.title);//Output the title i put in the html which is (Links)
transclude(scope, function(clone){
element.after(templateElement.append(clone));
});
}
};
});
the scope inside the link function(....) displaies the correct title but it doesn't work in the html:
Box {{ title }}
Link 1
Link 2
I think I missed one thing but I can't figure it out, I need your help to complete the cycle.
Thanx in advance,
The template element that contains the angular binding expressions must be compiled first, and then linked. The compilation phase prepares the template, while the linking phase sets up your $watchers for your binding expressions.
Demo Here
Here is a compile function that should work:
.directive('sideElement', function ($templateCache, $compile, $log) {
return {
restrict: 'A',
transclude: true,
scope:'#',
compile: function(element, attrs) {
var template = $templateCache.get(attrs.sideElement);
var templateElement = angular.element(template);
element.append(templateElement);
return function(scope, element, attr, ctrl, transclude) {
$log.info(scope.title);
}
}
}
I would like to create a list of items built in Directive and share through controllers.
Here is my example in plunker: Example of my code
Here is my code in js:
var app = angular.module('app', []);
app.controller("BrunchesCtrl", function ($scope, $log) {
$scope.brunches = [];
$scope.addNew = function () {
$scope.brunches.push({ address: "" });
};
$scope.$watch('brunch.address', function(value) {
$scope.address = value;
$log.info($scope.address);
});
$scope.$watch(function() { return $scope.brunches.length; }, function() {
$scope.brunches = $scope.brunches.map(function (brunch) {
return brunch;
});
});
});
app.directive('brunchesView', function ($compile) {
return {
restrict: 'E',
templateUrl: 'brunch.html',
controller: 'BrunchesCtrl',
replace: true,
link: function (scope, element, attrs, controller) {
}
};
});
app.directive('businessSubmit', function ($log, $compile, formManagerService) {
return {
restrict: 'AE',
controller: 'BrunchesCtrl',
link: function (scope, element, attrs, controller) {
formManagerService.init();
var hasError;
element.on('click', function (e) {
e.preventDefault();
$log.info("brunches: \n");
$log.info(scope.brunches);
});
}
};
});
Here is an HTML:
<!DOCTYPE html>
<div class="controls">
<a class="btn btn-danger" id="addBrunch" data-ng-click="addNew()">
<i class="icon-plus-sign"></i>
add new...
</a>
</div>
</div>
<brunches-view class="well" data-ng-repeat="brunch in brunches">{{brunch}}</brunches-view>
<br/>
<p class="well">
JSON: {{brunches | json}}
</p>
<div class="control-group">
<div class="controls">
<a class="btn btn-primary" href="#" data-business-submit>
<i class="icon-save"></i>
Save...
</a>
</div>
</div>
</div>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.0/angular.min.js"></script>
<script src="//netdna.bootstrapcdn.com/bootstrap/3.0.3/js/bootstrap.min.js"></script>
<script src="script.js"></script>
And here is the template:
<div class="fc-border-separate">
<div class="control-group">
<label class="control-label">Address</label>
<div class="controls">
<input type="text" class="span6 m-wrap"
name="Address" data-ng-model="address"
value="{{address}}" />
</div>
</div>
</div>
The final thing I want to save the whole data inside the BusinessSubmit directive.
Help please...
Several issues with your code.
First, your ng-model for the <input> is set to address, but the object you are wanting to bind it to a brunch object that has an address property. Important to realize that ng-repeat will create a child scope for every repeated item
<input data-ng-model="brunch.address"/>
Another issue is you are assigning the parent controller to a directive as well. Important to understand that controllers are singletons so if you use controller more than once , each is a separate instance. Therefore nesting the parent controller in a directive makes no sense.
DEMO- [ng-model] fix
If you want the data shared with other controllers you should set up a service that holds the brunches data by injecting it into whatever controllers will need access