I have a set of directives that share a scope
Update:
The code is available as a plunk here http://plnkr.co/edit/JZ77bsZgGrw6N4K718Is?p=preview
todo-item:
app.directive("todoItem",function(DeleteTodo,$log){
var dirDefObj = {
restrict:'E',
templateUrl:'app/templates/todo.html',
scope:{
todo:'=value'
},
controller:function($scope){},
replace:true
};
return dirDefObj;
});
template:
<div class="ui card">
<todo-formui ng-show="todo.editMode"></todo-formui>
<todo-cardui ng-show="!todo.editMode"></todo-cardui>
</div>
There are two directives that inherit the scope of this directive:
todo-cardui
app.directive('todoCardui',function(){
var dirDefObj = {
restrict:'E',
templateUrl:'app/templates/display-todo.html',
scope:false,
replace:true,
controller:function($scope)
{
$scope.clickDone = function clickDone(){
//two tasks (1)toggle the done value on the todo (2) toggle the btnText on the todo
$scope.todo.done = !$scope.todo.done;
$scope.todo.btnText = $scope.todo.done?'Reinstate':'Done';
};
$scope.remove = function remove()
{
DeleteTodo.delete($scope.todo);
$scope.$emit('todo:deleted',$scope.todo);
};
$scope.edit = function edit(value)
{
$scope.todo.editMode = true;
$scope.savedState = angular.extend({},$scope.todo);
};
}
};
return dirDefObj;
});
template:
<div>
<div class="content">
<i class="right floated blue pencil icon" ng-click="edit()"></i>
<header class="ui medium header">
<span ng-class="{'done-todo':todo.done,'normal-todo':!todo.done}">{{todo.task}}</span>
</header>
<div class="description">
<p>{{todo.description}}</p>
</div>
</div>
<div class="extra content">
<button class="ui small green toggle button floated left" ng-click="clickDone()">{{todo.btnText}}</button>
<button class="ui small red button floated left" ng-click="remove()">Delete</button>
</div>
</div>
todo-formui:
app.directive("todoFormui",function(EditService){
var dirDefObj = {
restrict:'E',
templateUrl:'app/templates/edit-todo.html',
scope:false,
controller:function($scope){
$scope.display = function display(){
console.log("Inside the edit to preview function");
$scope.editMode = false;
};
$scope.save = function(){
EditService.edit($scope.todo);
};
$scope.discard = function(){
$scope.todo={
task:'',
dscription:'',
btnText:''
};
$scope.todo = $scope.savedState;
};
},
replace:true
};
return dirDefObj;
});
template:
<div ng-class="{description:show_modal,content:!show_modal}">
<i class="right floated blue unhide icon" ng-click="display()"></i>
<form class="ui small form">
<div class="field">
<label>Task</label>
<input type="text" name="task" placeholder="What do you want to do?"ng-model="todo.task">
</div>
<div class="field">
<label>Description</label>
<textarea ng-model="todo.description"></textarea>
</div>
<div class="two fields">
<button class="ui red button floated right">Discard</button>
<button class="ui submit green button floated right" ng-click="save()">Save</button>
</div>
</form>
When executing the code,I found that the display function in todo-formui would not execute,no matter where I put it or what I tried to do.The save function in the same scope runs with no problems.
In your preview function(as mentioned in plunker), you have to update the scope as
$scope.todo.editMode = false;
instead of
$scope.editMode = false;
then the preview will be avaliable
Hope this helps
It's because the icon is under another html element and the click event isn't triggered. Add a clear after the "preview" icon (which is floated) to push the form where it should be. Use some DOM inspector and you will soon realize the problem.
Related
I am using angularjs and spring mvc for my application. At first I am displaying all the placements with one button Placed Candidates. I am doing ng-repeat for displaying all the placements.
Here is my html.
<div class="row" data-ng-repeat="placement in placements">
<div class="col-xs-12 col-sm-12 col-md-12">
<h5>{{placement.companyName}}</h5>
</div>
<div class="col-xs-12 col-sm-6 col-md-3">
<h6>{{placement.placementDate | date:'dd MMM yyyy'}}</h6>
Company Target (appox):10 Achieved:
</div>
<a href="javascript:void(0);" data-ng-
click="placedcandidatespopup(placement.placementId);">//here i can
get particular placementId but how to pass this id to
savePlacementStudents() method in controller.js???//
PlacedCandidates
</a>
</div>
I am calling one modal popup function. Here is controller.js
$scope.placedcandidatespopup = function()
{
AdminUsersService.getAllUsers().then(function(response)
{
$scope.allusers=response.data;
console.log($scope.allusers);
})
$(".placedcandidates").modal("show");
}
I am calling modal by name "placedcandidates".
Here is the modal
<div class="modal right fade placedcandidates" id="myModal1"
tabindex="-1" role="dialog" aria-labelledby="myModalLabel2">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-body">
<div class="row">
<div class="col-xs-12 col-sm-6 col-md-6" data-ng-
repeat="student in allusers">
<input id="{{student.studentId}}" type="checkbox" value="
{{student.studentId}}" data-ng-
checked="selection.indexOf(student.studentId) >-1"
data-ng-click="toggleSelection(student.studentId)"/>
<label for="{{student.studentId}}"></label>
{{student.firstName}}
</div>
</div>
</div>
<div class="modal-footer" style="position: fixed;">
<input type="button" value="Submit" class="btn" data-ng-
click="savePlacementStudents()">
</div>
</div>
</div>
</div>
After clicking on button popup modal will display with all Students with checkboxes placed beside them.Now I am able to save studentId into database.But I am not able to pass placementId for saving.
Here is my savePlacementStudents method in controller.js.
$scope.selectedStudents = {};
$scope.savePlacementStudents = function(selectedStudents)
{
selectedStudents.selectedList = $scope.selection;
AdminPlacementService.savePlacementStudents(selectedStudents).then
(function(response)
{
if(response.data=="success"){
$window.scrollTo(0,0);
$scope.selectedStudents = {};
$scope.getplacementdetails($scope.currentPageIndex);
$scope.successmessage="Student Selection Saved!;
$timeout(function() {
$scope.successmessage="";
$scope.closeplacedcandidatespopup();
}, 1500);
}
});
}
Can anyone tell how can I pass respective placementId to this saveStudents method() so that I can set that placementId for those students selected.
Here is the solution.
The placementId passed to function placedcandidatespopup can be saved as follows in function placedcandidatespopup
$scope.selectedPlacementId = placementId;
Now the same $scope will have access in Popup also as it is using same controller.js. And now you can use this $scope.selectedPlacementId anywhere in controller.js
So you don't need to pass placementId...!!
Hope that would help you..!!
$scope.placedcandidatespopup = function(id)
{
AdminUsersService.getAllUsers().then(function(response)
{
$scope.allusers=response.data;
console.log($scope.allusers);
})
$scope.inserted = {
placementId:id,
};
var modalInstance = $uibModal.open({
templateUrl: 'views/test/myModal1.html',
controller: 'TestCntrl',
size: "Modelwidth",
resolve: {
items: function () {
return $scope.inserted;
}
}
});
}
In model you have to access using items.placementId and when you savePlacementStudents() method send placementId as well with student info.
I am having an issue getting Angular Scroll to work.I am trying to scroll from the landing div to another section on the page with a button click. My code formatted really strangely, so let me know if further clarification is needed.
HTML
<div class="cover">
<div class="big-logo">
<i class="fa fa-trello"></i>
<span> My Kanban</span>
<br>
<button class="arrow" ng-click="bc.toLists()" du-smooth-scroll>
<i class="fa fa-angle-double-down fa-sm animated flash infinite" aria-hidden="true"></i>
</button>
</div>
</div>
<div class="story-board content">
<button class="add-list" ng-click="bc.addingList = !bc.addingList">
Add List
</button>
<div ng-if="bc.addingList">
<form ng-submit="bc.addList(bc.newList)">
<input style="margin-left: 5px" ng-model="bc.newList.name"/>
<button type="submit">+</button>
</form>
</div>
<div class="list" ng-repeat="list in bc.lists">
<button style="font-size: 10px;background: none;border:none; color: black" ng-click="bc.removeList(list)">x</button>
<list-component list-obj="list"></list-component>
</div>
</div>
init.js
angular.module('kanban', ['duScroll'])
app.js
angular.module('kanban')
.component('boardComponent', {
templateUrl: 'app/components/board/board.html',
controller: BoardController,
controllerAs: 'bc'
})
BoardController.$inject = ['EsService']
function BoardController(EsService) {
var bc = this;
bc.lists = EsService.getLists();
bc.addingList = false;
bc.removeList = function(list){
EsService.removeList(list.id);
}
bc.addList = function(list){
EsService.createList(list);
bc.newList = {};
}
bc.toLists = function() {
bc.cover = angular.element(document.getElementsByClassName('cover'));
bc.content = angular.element(document.getElementsByClassName('content'));
bc.cover.scrollTo(bc.content, 0, 1000);
}
}
For a JQuery free answer, you can use $anchorScroll
Create your anchor link:
<button ng-click="$ctrl.scrollTo('anid')">Scroll</button>
Create the anchor to scroll to:
<div id="anid">Land here</div>
Then your controller:
controller: function($anchorScroll) {
this.scrollTo = function(id) {
$anchorScroll(id);
}
}
I would recommend letting your controller handle the scrolling as opposed to the directives. You will have much tighter control that way and can therefore debug any issues.
Here's an example using the scrollToElement method. Once you have this logic in place you can switch it out to any method you need.
Here's a working demo
angular
.module('app', ['duScroll'])
.component('cmpExample', {
templateUrl: 'path/to/template.html',
controller: function($document) {
var vm = this;
vm.scrollTo = function(id) {
$document
.scrollToElement(
angular.element(document.getElementById(id)), 0, 1000
);
}
}
});
html
<button ng-click="$ctrl.scrollTo('target')">
<div id="target">Content further down the page</div>
I am an angular beginner and I wish to add an html button inside a popover that I am creating within a directive. Specifically, my directive allows the user to highlight text on the page and a popover will then appear around the selected text. It works for plain text content in the popover but not html. This is the directive as it is now
app.directive('replybox', function ($timeout, $window, $compile, $sce) {
var linkFn = function (scope, element, attrs) {
var exampleText= element.find('p');
var btn = element.find('button');
var windowSelection="";
exampleText.bind("mouseup", function () {
scope.sel = window.getSelection().toString();
windowSelection=window.getSelection().getRangeAt(0);
if(scope.sel.length>0) {
scope.showModal = true;
scope.$apply();
}
});
btn.bind("click", function () {
range = windowSelection;
var replaceText = range.toString();
range.deleteContents();
var div = document.createElement("div");
scope.pophtml = $sce.trustAsHtml("<p>hello world</p> <button>x</button>");
div.innerHTML = '<poper>' + replaceText + '</poper>';
var frag = document.createDocumentFragment(), child;
while ((child = div.firstChild)) {
frag.appendChild(child);
}
$compile(frag)(scope);
range.insertNode(frag);
scope.selection="None";
});
};
return {
link: linkFn,
restrict: 'A',
scope: {
entities: '=',
selection:'='
},
template: `<ng-transclude></ng-transclude>
<div class="modal fade in" style="display: block;" role="dialog" ng-show="showModal">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-body">
{{sel}}
</div>
<div class="radio">
<div ng-repeat="x in entities">
<div class="radio">
<label>
<input type="radio" name="choice" ng-model="$parent.selection" ng-value = "x">
{{x}}
</label>
</div>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-primary" ng-click="showModal=false">
Ok
</button>
</div>
</div>
</div>
</div>`,
transclude: true
};
});
The part that is not working is this part
scope.pophtml = $sce.trustAsHtml("<p>hello world</p> <button>x</button>");
div.innerHTML = '<poper>' + replaceText + '</poper>';
I have a feeling there is something wrong with the above two lines.
I am trying to modify a form in a view by means of a button in my directive's template (template is in another file), this is for a basic CRUD where each item has a delete/edit button.
In order to avoid replicating the form I decided to that on edit's click a function would send the item to the controller in questions in order to be updated with the new information.
But I've been having troubles making the connection, so far I tried changing $root, to $rootScope back and forth and using , $broadcast or $emit.
So how can I send the function onChange my item's information based on the template's button click?
Template:
<strong>{{item.type}}</strong> {{item.description}}
<div class="material-switch pull-right">
<button type="button" class="btn btn-warning btn-circle" ng-show="item.editable" ng-click="onChange()">
<span class="glyphicon glyphicon-edit" ></span>
</button>
<button type="button" class="btn btn-danger btn-circle" ng-controller="View1Ctrl" ng-show="item.editable" ng-click="EliminarItem(item)">
<span class="glyphicon glyphicon-minus" ></span>
</button>
<input ng-model="item.isDone"
id="someSwitchOptionDefault{{itemIndex}}"
name="someSwitchOption001{{itemIndex}}"
type="checkbox" />
<label for="someSwitchOptionDefault{{itemIndex}}" class="label-info"></label>
</div>
Directive:
'use strict';
angular.module('myApp.items.directive', [])
.directive('itemSwitch', [ function() {
return {
restrict: 'A',
scope: {
item: '=',
itemIndex: "="
},
templateUrl: 'templates/itemSwitchTemplate.html',
link : function($scope){
$scope.$broadcast('onChange', item);
}
}
}]);
Controller
.controller('View1Ctrl', ['$scope','itemsService',function($scope,itemsService) {
$scope.items = itemsService.getItems();
$scope.classMap = {GROCERIES:"success",CAR:"danger",UNIVERSITY:"warning",PAYMENTS:"info"};
$scope.newItem = {};
$scope.$on('onChange', function(event, args) {
if ($scope.btnEdit) {
$scope.newItem = args;
} else {
$scope.newItem = {};
}
});
$scope.enableEdit = function (item) {
item.editable = true;
};
$scope.disableEdit = function (item) {
item.editable = false;
};
}]);
View
<div class="col-xs-12">
<div ng-model="currentItem" ng-repeat="item in items" item-switch item="item" item-index="$index" class="notice notice-{{classMap[item.type]}}" ng-mouseover="enableEdit(item)" ng-mouseleave="disableEdit(item)">
</div>
<!-- FORMULARIO -->
<form name = "myForm" class="form-horizontal">
<fieldset>
<div id="legend">
<legend class="">Task</legend>
</div>
<div class="control-group">
<!-- Name-->
<label class="control-label">Name</label>
<div class="controls">
<input type="text" name="itemName" ng-model="newItem.name" placeholder="Task Name" class="input-xlarge" ng-required="true" >
<p class="help-block"></p>
</div>
</div>
<div class="control-group">
<!-- Description -->
<label class="control-label">Description</label>
<div class="controls" >
<input type="text" ng-model="newItem.description" placeholder="Task Description" class="input-xlarge">
<p class="help-block"></p>
</div>
</div>
<div class="control-group">
<!-- Button -->
<div class="controls">
<a class="btn icon-btn btn-success" ng-disabled="myForm.$invalid" ng-click="addOrSaveItem()">
<span class="glyphicon btn-glyphicon glyphicon-save img-circle text-success"></span>Save</a>
</div>
</div>
</fieldset>
</form>
</div>
FiddleJS
Look nd Feel
Using "onChange" as an event name is a poor choice as it is likely to conflict with other events with that name. My recommendation is to use the directive's name as part of the event name.
In your directive
angular.module('myApp.items.directive', [])
.directive('itemSwitch', function() {
return {
restrict: 'A',
scope: {
item: '=',
itemIndex: "="
},
template: '<button ng-click="doIt()">Do It</button>',
link : function(scope){
scope.doIt = function() {
scope.$emit('itemSwitch.doIt', scope.item, scope.itemIndex);
};
}
}
});
In your controller
$scope.doItItems = [];
$scope.$on("itemSwitch.doIt", function(item, itemIndex) {
doItItems.push(item);
});
In this example, on each click of the Do It button, an item is pushed to the doItItems list.
In your itemSwitch directive, you can do
$rootScope.$broadcast('onChange', item);
And then you can pick it up in any scope that is listening (in this case, your controller), with
$scope.$on('onChange', function(event, args) { ... }
This works because $broadcast moves downward from parent to children, while $emit moves upward from child to parents.
So for example, $rootScope.$emit would only be picked up by $rootScope.$on since $rootScope has no parents, while $scope.$broadcast would only be available to that scope's children and not to $rootScope.$on, since $rootScope is not a child of $scope
I am working with angular js for my dashboard. I have an over all minimize button to minimize all widget and then each widget have own minimize button. I done with following script its not working.
when i click widget minimize button its minimize all widget. but i want minimize that widget only.
var dashboard = angular.module("dashboard",['ui.bootstrap']);
dashboard.controller('dash-control', ['$scope', function($scope) {
$scope.isHidden = false;
$scope.toggle = function(){
$scope.isHidden = !$scope.isHidden;
};
$scope.toggleonce= function()
{
if( this.isHidden === true)
this.isHidden = false;
else
this.isHidden = true;
};
}]);
HTML code like follow:
<div class="contentpanel" ng-app="dashboard" ng-controller="dash-control as ctrl">
<button class="btn btn-white" type="button" ng-click="toggle()"><i class="fa fa-minus-square"> </i> </button>
<div>
<i class="fa fa-minus"></i>
<div class="row tinychart" ng-show="isHidden">Contenr Heading 1</div>
<div class="row tinychart" ng-hide="isHidden">Content Description 1</div>
</div>
<div>
<i class="fa fa-minus"></i>
<div class="row tinychart" ng-show="isHidden">Contenr Heading 2</div>
<div class="row tinychart" ng-hide="isHidden">Content Description 1</div>
</div>
......
.....
.....
</div>
I would rather create a directive with isolated scope for represent a inner widget. for instance;
dashboard.directive('myWidget',function(){
return {
scope:{},
template:"<div>\r\n<a href=\"\" class=\"tooltips\" ng-click=\"toggleonce()\" title=\"Minimize Panel\"><i class=\"fa fa-minus\"><\/i><\/a>\r\n<div class=\"row tinychart\" ng-show=\"isHidden\">asdasdasd<\/div>\r\n<div class=\"row tinychart\" ng-hide=\"isHidden\">sdasdasd<\/div>\r\n\r\n <\/div>",
link:function($scope)
{
$scope.isHidden = false;
$scope.toggle = function(){
$scope.isHidden = !$scope.isHidden;
};
$scope.togglesingle = function()
{
if( this.isHidden === true)
this.isHidden = false;
else
this.isHidden = true;
};
}
}
});
Then In Html Body;
<div class="contentpanel" ng-app="dashboard" >
<button class="btn btn-white" type="button" ng-click="toggle()"><i class="fa fa-minus-square"> </i> </button>
<div my-widget></div>
<div my-widget></div>
</div>
Note that I haven't run and check the example. I hope you got the idea.
Edited:
The ng-repeat will loop the array (list) and initiate each element to 'item' variable. You can pass that data to your directive. Check the updated code.