I can't access the parent รค$scope in my $mdBottomSheet. Iwant be able to create this bottom sheet and click one of the buttons inside of it displaying the parent $scope data. I made a codepen.
That's the code by the way:
<div ng-controller="BottomSheetExample" class="md-padding bottomSheetdemoBasicUsage" ng-cloak="" ng-app="MyApp">
<div class="bottom-sheet-demo inset" layout="row" layout-sm="column" layout-align="center">
<md-button flex="50" class="md-primary md-raised" ng-click="showGridBottomSheet()">Show as Grid</md-button>
</div>
<div ng-if="alert">
<br>
<b layout="row" layout-align="center center" class="md-padding">
{{alert}}
</b>
</div>
<script type="text/ng-template" id="bottom-sheet-grid-template.html"><md-bottom-sheet class="md-grid" layout="column" ng-cloak>
<div>
<md-list flex layout="row" layout-align="center center">
<md-list-item ng-repeat="item in items">
<div>
<md-button class="md-grid-item-content" ng-click="listItemClick($index)">
<md-icon md-svg-src="{{item.icon}}"></md-icon>
<div class="md-grid-text"> {{ item.name }} </div>
</md-button>
</div>
</md-list-item>
</md-list>
</div>
</md-bottom-sheet>
</script>
</div>
JavaScript:
angular.module('MyApp',['ngMaterial', 'ngMessages', 'material.svgAssetsCache'])
.config(function($mdIconProvider) {
$mdIconProvider
.icon('share-arrow', 'img/icons/share-arrow.svg', 24)
.icon('upload', 'img/icons/upload.svg', 24)
.icon('copy', 'img/icons/copy.svg', 24)
.icon('print', 'img/icons/print.svg', 24)
.icon('hangout', 'img/icons/hangout.svg', 24)
.icon('mail', 'img/icons/mail.svg', 24)
.icon('message', 'img/icons/message.svg', 24)
.icon('copy2', 'img/icons/copy2.svg', 24)
.icon('facebook', 'img/icons/facebook.svg', 24)
.icon('twitter', 'img/icons/twitter.svg', 24);
})
.controller('BottomSheetExample', function($scope, $timeout, $mdBottomSheet, $mdToast) {
$scope.alert = '';
$scope.items = [
{ name: 'Hangout', icon: 'hangout' },
{ name: 'Mail', icon: 'mail' },
{ name: 'Message', icon: 'message' },
{ name: 'Copy', icon: 'copy2' },
{ name: 'Facebook', icon: 'facebook' },
{ name: 'Twitter', icon: 'twitter' },
];
$scope.listItemClick = function($index) {
var clickedItem = $scope.items[$index];
$mdBottomSheet.hide(clickedItem);
};
$scope.showGridBottomSheet = function() {
$scope.alert = '';
$mdBottomSheet.show({
templateUrl: 'bottom-sheet-grid-template.html',
controller: function () {
return this;
},
preserveScope: true,
bindToController: true,
clickOutsideToClose: true
}).then(function(clickedItem) {
$mdToast.show(
$mdToast.simple()
.textContent(clickedItem['name'] + ' clicked!')
.position('top right')
.hideDelay(1500)
);
});
};
})
.run(function($http, $templateCache) {
var urls = [
'img/icons/share-arrow.svg',
'img/icons/upload.svg',
'img/icons/copy.svg',
'img/icons/print.svg',
'img/icons/hangout.svg',
'img/icons/mail.svg',
'img/icons/message.svg',
'img/icons/copy2.svg',
'img/icons/facebook.svg',
'img/icons/twitter.svg'
];
angular.forEach(urls, function(url) {
$http.get(url, {cache: $templateCache});
});
});
I can't see the buttons/icons inside the sheet.
Fiddle: https://jsfiddle.net/uvkr9zwe/
You need to parse your parent controller scope in the right way by instancing and referencing the parent controller scope.
Check this demo fiddle:
Your scope Action:
.controller('BottomSheetExample', function($scope, $timeout, $mdBottomSheet, $mdToast) {
$scope.alert = '';
$scope.items = [
{ name: 'Hangout', icon: 'hangout' },
{ name: 'Mail', icon: 'mail' },
{ name: 'Message', icon: 'message' },
{ name: 'Copy', icon: 'copy2' },
{ name: 'Facebook', icon: 'facebook' },
{ name: 'Twitter', icon: 'twitter' },
];
$scope.showGridBottomSheet = function() {
$mdBottomSheet.show({
templateUrl: 'bottom-sheet-grid-template',
controller: function () {
this.parent = $scope;
},
controllerAs: 'ctrl',
clickOutsideToClose: true
}).then(function(clickedItem) {
$mdToast.show(
$mdToast.simple()
.textContent(clickedItem['name'] + ' clicked!')
.position('top right')
.hideDelay(1500)
);
});
};
})
View Template:
<script type="text/ng-template" id="bottom-sheet-grid-template">
<md-bottom-sheet class="md-grid" layout="column" ng-cloak>
<div>
<md-list flex layout="row" layout-align="center center">
<md-list-item ng-repeat="item in ctrl.parent.items">
<div>
<md-button class="md-grid-item-content" ng-click="listItemClick($index)">
<md-icon md-svg-src="{{item.icon}}"></md-icon>
<div class="md-grid-text"> {{ item.name }} </div>
</md-button>
</div>
</md-list-item>
</md-list>
</div>
</md-bottom-sheet>
</script>
Related
is it possible with this example from Ben Foster to get all nodes closed by default (at the loading of the page) ? and to open each node with ng-click ?
http://jsfiddle.net/benfosterdev/NP7P5/
I have found a way to get selected node but I don't know how to combine it with ng-click and eventually ng-show or ng-hide:
ng-click='nodeSelected($event, category)'
and in controller
$scope.nodeSelected = function($event, category){
$event.stopPropagation();
console.log('This node is selected' + category);
}
Just found a similar example :
var gyroEditor = angular.module('gyroEditor', []);
gyroEditor.controller('Ctrl', function($scope) {
$scope.nodes = [
{
title: 'Computers',
categories: [
{
title: 'Laptops',
categories: [
{
title: 'Ultrabooks'
},
{
title: 'Macbooks'
}
]
},
{
title: 'Desktops'
},
{
title: 'Tablets',
categories: [
{
title: 'Apple'
},
{
title: 'Android'
}
]
}
]
},
{
title: 'Printers'
}
];
});
gyroEditor.directive('tree', function() {
return {
restrict: 'E',
replace: true,
scope: {nodes: '=nodes'},
templateUrl: 'tree.html',
controller: function($scope) {
console.log('tree ctrl');
}
};
});
gyroEditor.directive('treenode', function() {
return {
restrict: 'E',
replace: true,
scope: {node:'=node'},
templateUrl: 'treenode.html',
controller: function($scope) {
console.log('node ctrl');
}
};
});
gyroEditor.directive("recursive", function($compile) {
return {
restrict: "EACM",
priority: 100000,
compile: function(tElement, tAttr) {
var contents = tElement.contents().remove();
var compiledContents;
return function(scope, iElement, iAttr) {
if(!compiledContents) {
compiledContents = $compile(contents);
}
iElement.append(
compiledContents(scope,
function(clone) {
return clone; }));
};
}
};
});
.panel-left {
float: left;
width: 200px;
margin: 0 20px 20px 0;
}
.panel-editors {
float: right;
height: 100%;
width: 100%;
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.22/angular.min.js"></script>
<div ng-app=gyroEditor ng-controller=Ctrl>
<script type="text/ng-template" id="treenode.html">
<li ng-init="collapsed=true">
<a ng-click="collapsed=!collapsed"><i class="fa fa-{{((collapsed || !node.categories) ? '' : '-open')}}"></i> {{node.title}}</a>
<ol ng-if="!collapsed && node.categories && node.categories.length">
<recursive>
<treenode ng-repeat="c in node.categories" node=c>
</treenode>
</recursive>
</ol>
</li>
</script>
<script type="text/ng-template" id="tree.html">
<ol>
<treenode ng-repeat="n in nodes" node=n></treenode>
</ol>
</script>
<div class=panel-left>
<tree nodes=nodes></tree>
</div>
</div>
{{node.title}}
I have been trying to use an app level controller to display a modal dialog. Tests of the local function controller work perfectly, however the app level controller is displaying a grey shadow rather than the dialog as desired.
The results of edit and delete (in this example) should behave the same, but they are not.
Plunker link
Thanks in advance.
index.HTML
<!DOCTYPE html>
<html lang="en" ng-app="app">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="description" content="">
<meta name="author" content="">
<title>Sandbox Angular</title>
<!-- Bootstrap Core CSS -->
<link rel="stylesheet" href="assets/css/bootstrap.min.css">
<!-- Content CSS -->
<link rel="stylesheet" href="Content/angular-material.css">
<link rel="stylesheet" href="Content/ui-grid.css">
</head>
<!--<body ng-app="mainApp">-->
<body>
<div class="container">
<div ng-controller="HeaderGridCtrl">
<div class="grid" ui-grid="gridOptions" ui-grid-edit ui-grid-resize-columns></div>
</div>
</div>
<!-- /.container -->
<script src="Scripts/angular.js"></script>
<script src="Scripts/angular-material/angular-material.js"></script>
<script src="Scripts/angular-animate/angular-animate.js"></script>
<script src="Scripts/angular-aria/angular-aria.js"></script>
<script src="Scripts/ui-grid.js"></script>
<script src="app/app.module.js"></script>
</body>
</html>
testEdit.HTML
<md-dialog>
<div>
<form ng-cloak>
<md-toolbar>
<div class="md-toolbar-tools">
<h2>{{firstName}} {{lastName}} ({{action}})</h2>
<span flex></span>
</div>
</md-toolbar>
<md-dialog-content>
<div class="md-dialog-content">
<p>
Life's actions....make sure the juice is worth the squeeze.
</p>
</div>
</md-dialog-content>
</form>
</div>
testDelete.HTML
<md-dialog>
<div ng-controller="DetailRecordCtrl">
<form ng-cloak>
<md-toolbar>
<div class="md-toolbar-tools">
<h2>{{firstName}} {{lastName}} ({{action}})</h2>
<span flex></span>
</div>
</md-toolbar>
<md-dialog-content>
<div class="md-dialog-content">
<h2>{{firstName}} {{lastName}} ({{action}})</h2>
<p>
Life's actions....make sure the juice is worth the squeeze.
</p>
</div>
</md-dialog-content>
</form>
</div>
app.module.js
(function () {
'use strict';
//,'ui.router''ngGrid'
var app = angular.module('app', ['ngMaterial', 'ui.grid', 'ui.grid.resizeColumns']);
app.controller('DetailRecordCtrl', ['$scope', '$mdDialog', 'action', 'currentRow', initDetail])
app.controller('HeaderGridCtrl', ['$scope', '$mdDialog', initGrid]);
app.controller('testDialogCtrl', ['$scope', '$mdDialog', initModalTest]);
//---------------------------------
app.run([function () {
/* Run is when the app gets kicked off*/
console.log("Run processed");
}])
//---------------------------------
function initDetail($scope, $mdDialog, action, currentRow) {
$scope = $scope;
$scope.action = action;
$scope.firstName = currentRow.entity.firstName;
$scope.lastName = currentRow.entity.lastName;
$scope.closeDialog = function () {
$mdDialog.hide();
};
}
//---------------------------------
function initGrid($scope, $mdDialog) {
var currentRow = 0;
$scope.showDelete = function (ev, keyAction, row) {
$mdDialog.show({
locals: { action: keyAction, currentRow: row },
controller: 'DetailRecordCtrl',
scope: $scope,
preserveScope: true,
targetEvent: ev,
clickOutsideToClose: true,
skipHide: true,
fullscreen: $scope.customFullscreen // Only for -xs, -sm breakpoints.
})
};
$scope.showEdit = function (ev, keyAction, row) {
$mdDialog.show({
locals: { action: keyAction, currentRow: row },
controller: LocalDetailRecordCtrl,
templateUrl: 'testEdit.html',
scope: $scope,
preserveScope: true,
ariaLabel: 'Edit Record',
targetEvent: ev,
clickOutsideToClose: true,
fullscreen: $scope.customFullscreen // Only for -xs, -sm breakpoints.
})
};
$scope.editIcon = '<button class="md-primary md-raised" ng-click="grid.appScope.showEdit($event,\'EDIT\',row)">EDIT</button> ';
$scope.deleteIcon = '<button class="md-primary md-raised" ng-click="grid.appScope.showDelete($event,\'DELETE\',row)">DELETE</button>';
$scope.info = [{ firstName: "Jimmy", lastName: "John", grade: '1st', contributionDay01: 5.12, total: 0 },
{ firstName: "Jane", lastName: "Pauley", grade: '2nd', contributionDay01: 4, total: 0 },
{ firstName: "Andrea", lastName: "Kragel", grade: '3rd', contributionDay01: 11.28, total: 0 },
{ firstName: "Zebra", lastName: "Zoo", grade: 'PK', contributionDay01: 19.23, total: 0 },
{ firstName: "Jaguar", lastName: "Meowser", grade: 'K', contributionDay01: 25, total: 0 }];
$scope.gridOptions = {
data: 'info',
enableFiltering: true,
enableColumnResizing: true,
enableSorting: false,
enableRowHeaderSelection: true,
enableColumnMenus: true,
enableCellEditOnFocus: true,
enableRowSelection: true,
enableCellEdit: true,
noUnselect: false,
cellTemplate: '<div ng-repeat="col in renderedColumns"></div>',
columnDefs: [
{
field: 'wrkDisplay', displayName: 'Actions', enableCellEdit: false, width: '*'
, cellTemplate:
'<div class="testClass">' + $scope.editIcon + ' ' + $scope.deleteIcon + ' ' +
'</div>'
},
{ field: 'firstName', displayName: 'First Name', enableCellEdit: true, minWidth: 100, },
{ field: 'lastName', displayName: 'Last Name', enableCellEdit: true, minWidth: 100 },
{ field: 'grade', displayName: 'Grade', enableCellEdit: true, minWidth: 70 },
{ field: 'getFullName()', displayName: 'Teacher', enableCellEdit: true, minWidth: 100 },
{ field: 'contributionDay01', displayName: 'Day1', enableCellEdit: true, minWidth: 50, cellFilter: 'number: 2' },
{ field: 'getTotal()', displayName: 'Total', enableCellEdit: false, cellFilter: 'currency' }]
};
//Calaculated fields
angular.forEach($scope.info, function (row) {
row.getTotal = function () {
return this.contributionDay01 * 11;
}
row.getFullName = function () {
return (this.firstName + ' ' + this.lastName);
}
});
function LocalDetailRecordCtrl($scope, $mdDialog, action, currentRow) {
$scope.action = action;
$scope.firstName = currentRow.entity.firstName;
$scope.lastName = currentRow.entity.lastName;
$scope.closeDialog = function () {
$mdDialog.hide();
}
};
}
})();
Issue resolved after looking at the Angular $mdDialog documentation for the n-th time.
The controller listed under the $mdDialog.show method can be declared both with or without quotes.
Without quotes uses the local $scope function defined.
With quotes uses the app level controller [i.e. app.controller(...)] Additionally, the template / templateUrl can be used.
This now enables me to have a single HTML detail record page that can be accessed from multiple data points if necessary.
I want to bind the c3chart id to div id present in md-dialog. But when I try to get the div id by document.getElementById it returns null to me. I dont know what I'm missing. I'm new to angularjs and not able to find out the cause chart not binding to div id.
Below the html template I'm trying to load for the dialog :
<md-dialog aria-label="Export Image" ng-cloak>
<md-toolbar>
<div class="md-toolbar-tools">
<h2>Export Image</h2>
<span flex></span>
<md-button class="md-icon-button" ng-click="cancel()">
<md-icon aria-label="Close dialog">close</md-icon>
</md-button>
</div>
</md-toolbar>
<md-content layout-padding>
<div class='legend2'></div>
<div id="chart"></div>
<div class='legend1'></div>
<div layout="row" layout-align="center center">
<md-button md-menu-origin ng-click="exportToPng()">
<span>Save as PNG</span>
</md-button>
<md-button md-menu-origin ng-click="exportToSvg()">
<span>Save as SVG</span>
</md-button>
</div>
</md-content>
</md-dialog>
Below is the service I'm using to load md-dialog on clicking the image export button:
$mdDialog.show({
controller: 'ExportImagesDisplayCtrl',
templateUrl: templateUrl,
parent: angular.element(document.body),
targetEvent: ev,
locals: {
stats: stats,
filterKey: filterKey,
filterType: filterType
},
clickOutsideToClose: true
});
Below is the part of the controller where I'm trying to bind the chart to div id:
$scope.drawC3Chart = function(chartGroup){
var element = document.getElementById("chart");
var chart = c3.generate({
bindto: element,
size: {
height: 235,
width: 330
},
data: {
type: 'bar',
json: chartGroup,
keys: {
x:'name',
value: ['to', 'from'],
}
},
axis: {
x:{
type:'category',
label: {
text: 'from/to',
position: 'outer-center'
}
},
y:{
label: {
text: 'count',
position: 'outer-middle'
}
}
},
grid: {
y: {
show: true
}
},
legend: {
show: false
},
regions: [
{axis: 'x', end: 1.5 , class:'regionX2'},
{axis: 'x', start: 1.5, end: 6, class:'regionX1' },
]
});
}
You must access to 'chart' element after dialog load progress complete or use $timeout instead:
$mdDialog.show({
controller: 'ExportImagesDisplayCtrl',
templateUrl: templateUrl,
parent: angular.element(document.body),
targetEvent: ev,
locals: {
stats: stats,
filterKey: filterKey,
filterType: filterType
},
clickOutsideToClose: true,
onComplete: function(){
$scope.drawC3Chart(); // <---- TODO: draw your chart at here
}
});
I'm using a directive to set html, css and javascript code inside of and iframe. These iframes are inside a ng-repeat, so there is an iframe per result.
Then these results are filtered by title and sortby title or date.
So, I have two problems:
Firefox is not showing the iframe html code but the rest of the browsers are.
After selecting a sort option, the title and date are refresing correctly, but the iframe content is not.
Here is a link to Plunker: http://plnkr.co/edit/Kvsbir?p=info
And here is my code:
<body ng-controller="HomeController">
<div class="panel-heading text-center">
<h3>Projects</h3>
<form action="" class="form-inline">
<div class="form-group">
<input class="form-control" type="text" ng-model="query.name" placeholder="Search...">
</div>
<div class="form-group dropdown">
<select class="btn btn-default dropdown-toggle" type="text" ng-model="sortOrder" ng-options="item.value as item.text for item in sortOptions"></select>
</div>
</form>
</div>
<div class="panel-body">
<div ng-model="result" ng-repeat="project in projects | orderBy:sortOrder | filter:query.name" class="col-md-4 col-sm-6">
<div class="single-pen">
<div class="meta">
<h3>{{project.title}}</h3>
<h6> {{project.created_at | date}} </h6>
</div>
<div class="iframe-wrap">
<div theframe="project"></div>
</div>
</div>
</div>
</div>
</body>
The controller
var app = angular.module('plunker', []);
app.controller('HomeController', function ($rootScope,$filter, $scope) {
'use strict';
var vm = this;
// Filter & sort
$scope.sortOptions = [
{ value: "-created_at", text: "Ordenar by Date"},
{ value: "title", text: "Ordenar by Title"}
];
$scope.sortOrder = $scope.sortOptions[0].value;
$scope.result = [
{
title: 'Project 1',
code: [{
css: "body{background-color: pink;}",
html: "<h1>Hello</h1>",
js: ""
}],
created_at: "2016-02-06T22:52:24.900Z"
},
{
title: 'Project 2',
code: [{
css: "body{background-color: blue;}",
html: "<h1>Hello</h1>",
js: ""
}],
created_at: "2016-02-10T11:52:33.055Z"
},
{
title: 'Project 3',
code: [{
css: "body{background-color: yellow;}",
html: "<h1>Hello</h1>",
js: ""
}],
created_at: "2016-02-06T22:52:24.900Z"
},
{
title: 'Project 4',
code: [{
css: "body{background-color: orange;}",
html: "<h1>Hello</h1>",
js: ""
}],
created_at: "2016-02-08T11:52:33.055Z"
},
{
title: 'Project 5',
code: [{
css: "body{background-color: red;}",
html: "<h1>Hello</h1>",
js: ""
}],
created_at: "2016-02-01T13:46:33.917Z"
},
];
$scope.projects = $scope.result;
})
.directive('theframe', function($compile){
return {
restrict: 'A',
scope: {
theframe: '='
},
template: '<iframe id="frame" scrolling="no"></iframe>',
link: function($scope, element, attrs) {
var $head = $(element).find('#frame').contents().find('head');
var $body = $(element).find('#frame').contents().find('body');
$scope.$watch('projects', function(n,o){
$head[0].innerHTML = '<style>'+$scope.theframe.code[0].css+'</style>';
$body[0].innerHTML = $scope.theframe.code[0].html + '<script> (function(){ \n' + $scope.theframe.code[0].js + '\n})();</script>';
}, true);
}
}
})
Any hints of why is not working correctly?
EDIT
SOLVED Firefox issue!
Thanks for the $timeout idea.
This is what i've changed: http://plnkr.co/edit/Kvsbir?p=preview
.directive('theframe', function($compile, $timeout){
return {
restrict: 'A',
scope: {
theframe: '='
},
template: '<iframe id="frame" scrolling="no"></iframe>',
link: function($scope, element, attrs) {
var $head = $(element).find('#frame').contents().find('head');
var $body = $(element).find('#frame').contents().find('body');
var timeout = setInterval(function(){
$head[0].innerHTML = '<style>'+$scope.theframe.code[0].css+'</style>';
$body[0].innerHTML = $scope.theframe.code[0].html + '<script> (function(){ \n' + $scope.theframe.code[0].js + '\n})();</script>';
$scope.$apply();
}, 500);
}
}
})
This should be a simple question, currently am displaying widget types on the left side of the navigation and i have a widget array. Based on the Widget Title selection i need to filter the types from the widget and display on the right.
Here is the code which i have right now,
App.js
$scope.WidgetTypes = [
{
title: 'Chart',
icon: 'styles/css/images/icons/ic_insert_chart_24px.svg'
},
{
title: 'Blogging',
icon: 'styles/css/images/icons/ic_assignment_24px.svg'
},
{
title: 'Advertising',
icon: 'styles/css/images/icons/ic_av_timer_24px.svg'
},
{
title: 'Custom',
icon: 'styles/css/images/icons/ic_dashboard_24px.svg'
},
{
title: 'Social Media',
icon: 'styles/css/images/icons/ic_now_widgets_24px.svg'
} ,
{
title: 'Web Analytics',
icon: 'styles/css/images/icons/ic_gradient_24px.svg'
}
];
$scope.Widgets = [
{
title: 'Google SpreadSheets',
icon: 'styles/css/images/icons/ic_insert_chart_24px.svg',
type:"Chart",
Description:'Line, Area, Bar, Pie, Table'
} ,
{
title: 'LinkedIn',
icon: 'styles/css/images/icons/ic_dashboard_24px.svg',
type:"Social Media",
Description:'Connections, Network Updates'
},
{
title: 'Pinterest',
icon: 'styles/css/images/icons/ic_dashboard_24px.svg',
type:"Social Media",
Description:'Boards, Pins, Likes, Followers, Following'
},
{
title: 'Google Analytics (Real Time)',
icon: 'styles/css/images/icons/ic_dashboard_24px.svg',
type:"Web Analytics",
Description:'Audience, Traffic, Content, Conversions'
}
];
HTML:
<md-list-item class="md-3-line" ng-repeat="widget in Widgets ">
<div layout="row" layout-margin>
<div flex="60">
<img ng-src="{{widget.icon}}" class="md-avatar" alt="{{widget.title}}">
<div class="md-list-item-text">
<h4>{{ widget.title }}</h4>
<h5>{{ widget.Description }}</h5>
</div>
</div>
<div flex="20">
<md-button style="width:100px" class="md-raised">
Add
</md-button>
</div>
</div>
<md-divider></md-divider>
</md-list-item>
Here is the Plunker
You in the right direction already you only have to implement which is selected & filter
$scope.filterWidgets = function(item)
{
$scope.selected = {};
$scope.selected.type = item.title;
console.log(selected);
};
and
<md-list-item class="md-3-line" ng-repeat="widget in Widgets | filter : selected">
http://plnkr.co/edit/8M8tNAmV1dARIu4OfFcl?p=preview