I'm trying to set a list of two items that open separate modal dialogs in a node.js app. I'm using Jade.
Here's the Jade:
button.login-button(type='button' ng-app='ng-modal') Login
ul
li(open-dialog='modal-to-open') Login
// JUST WORKING ON SIGN UP FOR NOW
li Sign Up
modal-dialog(show='dialogShown' dialog-title='My Dialog' height='100px' width='100px')
p Working
div.loginForm
form(name='loginForm' method='post' action='#' enctype='text/plain')
label(for='user') Username or Email
input(type='text' name='username' id='username' size="39" placeholder='Username or Email' required)
label(for='password') Password
input(type='password' name='password' id='password' size='39' placeholder='Password' required)
I'm using Adam Brecht's modal dialog plugin. I have the js file and the css files attached.
I changed the declaration of the module in the js file to this:
app = angular.module("myApp", ["ngModal"])
I have the list set as a dropdown in my CSS. I wanted the form to display in a modal dialog when the link in the list is clicked, but at the moment the form displays below dropdown box.
What am I missing?
EDIT: This is the js file:
(function() {
var app;
app = angular.module("myApp", ["ngModal"])
app.provider("ngModalDefaults", function() {
return {
options: {
closeButtonHtml: "<span class='ng-modal-close-x'>X</span>"
},
$get: function() {
return this.options;
},
set: function(keyOrHash, value) {
var k, v, _results;
if (typeof keyOrHash === 'object') {
_results = [];
for (k in keyOrHash) {
v = keyOrHash[k];
_results.push(this.options[k] = v);
}
return _results;
} else {
return this.options[keyOrHash] = value;
}
}
};
});
app.directive('modalDialog', [
'ngModalDefaults', '$sce', function(ngModalDefaults, $sce) {
return {
restrict: 'E',
scope: {
show: '=',
dialogTitle: '#',
onClose: '&?'
},
replace: true,
transclude: true,
link: function(scope, element, attrs) {
var setupCloseButton, setupStyle;
setupCloseButton = function() {
return scope.closeButtonHtml = $sce.trustAsHtml(ngModalDefaults.closeButtonHtml);
};
setupStyle = function() {
scope.dialogStyle = {};
if (attrs.width) {
scope.dialogStyle['width'] = attrs.width;
}
if (attrs.height) {
return scope.dialogStyle['height'] = attrs.height;
}
};
scope.hideModal = function() {
return scope.show = false;
};
scope.$watch('show', function(newVal, oldVal) {
if (newVal && !oldVal) {
document.getElementsByTagName("body")[0].style.overflow = "hidden";
} else {
document.getElementsByTagName("body")[0].style.overflow = "";
}
if ((!newVal && oldVal) && (scope.onClose != null)) {
return scope.onClose();
}
});
setupCloseButton();
return setupStyle();
},
template: "<div class='ng-modal' ng-show='show'>\n <div class='ng-modal-overlay' ng-click='hideModal()'></div>\n <div class='ng-modal-dialog' ng-style='dialogStyle'>\n <span class='ng-modal-title' ng-show='dialogTitle && dialogTitle.length' ng-bind='dialogTitle'></span>\n <div class='ng-modal-close' ng-click='hideModal()'>\n <div ng-bind-html='closeButtonHtml'></div>\n </div>\n <div class='ng-modal-dialog-content' ng-transclude></div>\n </div>\n</div>"
};
}
]);
}).call(this);
I just realized I haven't changed the template.
Related
No matter what I select, this function only returns the first item of the list. As requested, I have included the complete JS code. I have looked through this code four hours and everything seems right to me. This is my first contact with Angular and any help will be greatly appreciated!
Thank you!
HTML
<div class="form-horizontal input-append">
<select name="selectedSharedTenantId" data-ng-model="selectedSharedTenantId">
<option data-ng-repeat="item in getFilteredTenants()" value="{{item.id}}">{{item.displayName}}</option>
</select>
<button type="button" class="btn" ng-click="addSharedTenant();">
<i class="fas fa-plus"></i>
</button>
</div>
JS
$scope.addSharedTenant = function () {
alert($scope.selectedSharedTenantId)
}
COMPLETE JS CODE
angular.module('directives.datasetEditor', [
'services.dataset',
'ui.bootstrap'
])
.directive('datasetEditor', ['$modal', 'DatasetServices', function ($modal, DatasetServices) {
return {
restrict: 'A',
scope: {
tenantId: '=',
tenants: '=',
originalModel: '=model',
callback: '&callback'
},
link: function(scope, element, attrs) {
scope.model = scope.originalModel ? angular.copy(scope.originalModel) : {
entryType: 'Activity',
displayName: ''
};
var ModalInstanceCtrl = ['$scope', '$modalInstance',
function($scope, $modalInstance) {
var setSelectedSharedTenantId = function () {
var selectedTenant = $scope.getFilteredTenants()[0];
$scope.selectedSharedTenantId = selectedTenant ? selectedTenant.id : null;
};
$scope.getFilteredTenants = function () {
return _.filter($scope.tenants, function (o) {
alert(o.id)
return _.indexOf($scope.model.sharedTenantIds, o.id) == -1 && o.id != $scope.tenantId;
});
};
$scope.getTenantById = function (id) {
return _.findWhere($scope.tenants, {
id: id
});
};
$scope.removedSharedTenant = function (id) {
$scope.model.sharedTenantIds = _.without($scope.model.sharedTenantIds, id);
var selectedTenant = $scope.getFilteredTenants()[0];
setSelectedSharedTenantId();
};
$scope.addSharedTenant = function () {
//alert($scope.selectedSharedTenantId)
//alert($scope.model.sharedTenantIds)
if ($scope.selectedSharedTenantId) {
if ($scope.model.sharedTenantIds == null) {
$scope.model.sharedTenantIds = [];
}
$scope.model.sharedTenantIds.push($scope.selectedSharedTenantId);
setSelectedSharedTenantId();
}
};
$scope.submit = function(isValid) {
if (isValid) {
DatasetServices.save($scope.model).success(function(data, status, headers, config) {
$modalInstance.close(data);
});
} else {
$scope.submitted = true;
}
};
$scope.cancel = function() {
$modalInstance.dismiss();
};
$scope.submitted = false;
setSelectedSharedTenantId();
}];
function open() {
var modalInstance = $modal.open({
templateUrl: '../pkg/wisdom/common/angular/directives/dataset-editor/index.html',
controller: ModalInstanceCtrl,
scope: scope
});
modalInstance.result.then(
function(model) {
scope.callback({
model: model
});
},
function() {
}
);
};
element.on('click', open);
}
};
}]);
I have a custom search directive and need to use multiple instances of it on the same page. The page makes use of bootstrap tabs and there will be an instance of this search component in each tab.
The issue is that the search directive in the second tab is overriding the callback of the search directive in the first tab. Here is a snippet of my search directive:
class SearchDirective {
constructor($timeout) {
this.require = '^ngModel';
this.restrict= "AE";
this.$timeout = $timeout;
this.scope = {
ngModel: '=',
searchTime: '=',
searchCallback: '&'
};
}
compile(tElem, tAttrs) {
return this.link.bind(this);
}
link(scope, element, attrs) {
this.scope = scope;
var timer = null;
scope.$watch('ngModel', (value, preValue) => {
if (value === preValue) return;
if (timer) {
this.$timeout.cancel(timer);
}
timer = this.$timeout(() => {
timer = null;
if (value.length === 0) {
this.scope.searchCallback();
}
}, this.scope.searchTime)
});
}
}
And here is a snippet of the HTML for the search component on the first tab:
<input search search-callback="searchWindowsController.searchPcs()" search-time="600" data-ng-model="searchWindowsController.searchQuery" type="text" class="searchBox" placeholder="Search Windows...">
And this is what i have in the second tab:
<input search search-callback="searchMacController.searchPcs()" search-time="600" data-ng-model="searchMacController.searchQuery" type="text" class="searchBox" placeholder="Search Macs...">
For some reason when you search using the Windows search, it is calling the Mac callback. Can someone point me to what I am doing wrong? I am new to custom directives.
The error due to this within the $timeout function.
See live example on jsfiddle.
'use strict'
var myApp = angular.module('myApp', []);
myApp.controller('MyCtrl', function($scope, $log) {
$scope.callback1 = function(){
console.log('callback1');
};
$scope.callback2 = function(){
console.log('callback2');
};
})
.directive('search',function($timeout){
return new SearchDirective($timeout);
});
class SearchDirective {
constructor(timeout) {
this.require = '^ngModel';
this.restrict = "AE";
this.$timeout = timeout;
this.scope = {
ngModel: '=',
searchTime: '=',
searchCallback: '&'
};
}
compile(tElem, tAttrs) {
return this.link.bind(this);
}
link(scope, element, attrs) {
this.scope = scope;
var timer = null;
scope.$watch('ngModel', (value, preValue) => {
if (value === preValue) return;
if (timer) {
this.$timeout.cancel(timer);
}
timer = this.$timeout(() => {
timer = null;
if (value.length === 0) {
scope.searchCallback();
}
}, scope.searchTime)
});
}
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.8/angular.min.js"></script>
<div ng-app="myApp">
<div ng-controller="MyCtrl">
<input search search-callback="callback1()" search-time="600" data-ng-model="searchQuery1" type="text" class="searchBox" placeholder="Search Mac...">
<input search search-callback="callback2()" search-time="600" data-ng-model="searchQuery2" type="text" class="searchBox" placeholder="Search Windows...">
</div>
</div>
So far i can access my webcan and show the streaming and take a snapshot. What i want to do in the end is change the source for another webcam, so first i will need to list all webcam installed and if possible, select another source. Any ideas on how to access and list all webcams using angularJS?
Code so far:
<script>
/////////////////////////////////////////////
var getUserMedia = function() {
if (navigator.getUserMedia) return navigator.getUserMedia;
else if (navigator.webkitGetUserMedia) return navigator.webkitGetUserMedia;
else if (navigator.mozGetUserMedia) return navigator.mozGetUserMedia;
else if (navigator.msGetUserMedia) return navigator.msGetUserMedia;
else return undefined;
}
//console.log(getUserMedia());
/////////////////////////////////////////////
angular.module('app')
.factory('CameraService', function($window) {
var hasUserMedia = function() {
return !!getUserMedia();
}
var getUserMedia = function() {
navigator.getUserMedia = ($window.navigator.getUserMedia ||
$window.navigator.webkitGetUserMedia ||
$window.navigator.mozGetUserMedia ||
$window.navigator.msGetUserMedia);
return navigator.getUserMedia;
}
return {
hasUserMedia: hasUserMedia(),
getUserMedia: getUserMedia
}
})
////////////////////////////////////////////
angular.module('app')
.controller('CameraController', function($scope, CameraService) {
$scope.hasUserMedia = CameraService.hasUserMedia;
})
////////////////////////////////////////////
angular.module('app')
.directive('camera', function(CameraService) {
return {
restrict: 'EA',
replace: true,
transclude: true,
scope: {},
controller: function($scope, $q, $timeout) {
this.takeSnapshot = function() {
var canvas = document.querySelector('canvas'),
ctx = canvas.getContext('2d'),
videoElement = document.querySelector('video'),
d = $q.defer();
canvas.width = $scope.w;
canvas.height = $scope.h;
$timeout(function() {
ctx.fillRect(0, 0, $scope.w, $scope.h);
ctx.drawImage(videoElement, 0, 0, $scope.w, $scope.h);
d.resolve(canvas.toDataURL());
}, 0);
return d.promise;
}
},
template: '<div class="camera"><video class="camera" my-stream config="config" autoplay="" /><div ng-transclude></div><canvas></div>',
link: function(scope, ele, attrs) {
var w = attrs.width || 640,
h = attrs.height || 480;
if (!CameraService.hasUserMedia) return;
var userMedia = CameraService.getUserMedia(),
videoElement = document.querySelector('video');
var onSuccess = function(stream) {
if (navigator.mozGetUserMedia) {
videoElement.mozSrcObject = stream;
} else {
var vendorURL = window.URL || window.webkitURL;
videoElement.src = window.URL.createObjectURL(stream);
}
// Just to make sure it autoplays
videoElement.play();
}
// If there is an error
var onFailure = function(err) {
console.error(err);
}
// Make the request for the media
navigator.getUserMedia({
video: {
mandatory: {
maxHeight: h,
maxWidth: w
}
},
audio: true
}, onSuccess, onFailure);
scope.w = w;
scope.h = h;
}
}
});
angular.module('app').directive('cameraControlSnapshot', function() {
return {
restrict: 'EA',
require: '^camera',
scope: true,
template: '<a class="btn btn-info" ng-click="takeSnapshot()">Take snapshot</a>',
link: function(scope, ele, attrs, cameraCtrl) {
scope.takeSnapshot = function() {
cameraCtrl.takeSnapshot()
.then(function(image) {
// data image here
});
}
}
}
})
</script>
in the HTML
<body ng-app="app">
<a class="btn btn-info" ng-click="enabled=!enabled">Camera</a>
<!-- ngIf: enabled -->
<div class="camera ng-scope ng-isolate-scope" ng-if="enabled">
<!--camera></camera-->
<camera>
<camera-control-snapshot></camera-control-snapshot>
</camera>
</div><!-- end ngIf: enabled --><!-- end ngIf: enabled --><!-- end ngIf: enabled -->
</body>
You're using the wrong API. Using Google, I found MDN documentation for Navigator.enumerateDevices. The documentation is for the newer mediaDevices object, but this may be available on the Navigator object for the time being. You'll have to check whether the property exists. Based on the documentation, you should be able to filter the array returned by the function call.
As for Angular, once you have this information, it's as simple as an ng-repeat.
We have requirement to show a drop down when user enters a "#".
I am planning to have a directive as following:
app.controller('MainCtrl', function($scope) {
$scope.values = ['#'];
$scope.valuesEntered = false;
});
app.directive('identifier', function ($parse) {
return {
scope: {
values: '=values'
},
link: function (scope, elm, attrs) {
elm.bind('keypress', function(e){
var char = String.fromCharCode(e.which||e.charCode||e.keyCode), matches = [];
angular.forEach(scope.values, function(value, key){
if(char === value) matches.push(char);
}, matches);
if(matches.length !== 0){
$scope.valuesEntered = true;
}
});
}
}
});
Will this be ok ?
Here is a simple directive I made that will allow you to specify an expression to evaluate when a given key is pressed or one of an array of keys is pressed.
Note that this is a one-way street. There is currently no going back once you have detected that keypress, even if the user pressed backspace.
var app = angular.module('sample', []);
app.controller('mainCtrl', function($scope) {
$scope.values = ['#', '!'];
$scope.valuesEntered = false;
$scope.valuesEntered2 = false;
});
app.directive('whenKeyPressed', function($parse) {
return {
restrict: 'A',
scope: {
action: '&do'
},
link: function(scope, elm, attrs) {
var charCodesToMatch = [];
attrs.$observe('whenKeyPressed', function(keys) {
if (angular.isArray(keys))
charCodesToMatch = keys.map(function(key) {
if (angular.isString(key))
return key.charCodeAt(0);
});
else if (angular.isString(keys))
charCodesToMatch = keys.split('').map(function(ch) {
return ch.charCodeAt(0);
});
});
elm.bind('keypress', function(e) {
var charCode = e.which || e.charCode || e.keyCode;
if (charCodesToMatch.indexOf(charCode) > -1)
scope.action();
});
}
}
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="sample">
<div ng-controller="mainCtrl">
<p>Values "#" entered? {{valuesEntered}}</p>
<textarea ng-model="str" when-key-pressed="#" do="valuesEntered = true"></textarea>
<p>Values {{values}} entered 2: {{valuesEntered2}}</p>
<textarea ng-model="str2" when-key-pressed="{{values}}" do="valuesEntered2 = true"></textarea>
</div>
</div>
Plunkr demo
Using ui-bootstrap I have a really simple custom directive that lists alerts at the top of the page. On normal pages it works like a champ. When I use my directive inside a $modal popup I get "undefined is not a function" at ngRepeatAction.
The directive I have behind the modal on the main page still works. I can see it behind the modal. It's just the one in the modal popup that breaks. What am I doing wrong?
Modal open code:
$modal.open({
templateUrl: 'partials/main/servers/serverAuths/edit.html',
controller: function($scope, $modalInstance) {
$scope.auth = angular.copy(auth);
$scope.auth.password = null;
$scope.saveAuth = function() {
Auths.editAuth($scope.auth).then(
function(resp) {
if (resp.rc===0) {
Alerts.addAlert('success', 'Auth `'+$scope.auth.name+'` saved.');
_.extend(auth, $scope.auth);
$modalInstance.close();
} else {
Alerts.addAlert('danger', 'Auth `'+$scope.auth.name+'` could not be saved. ' + resp.message, 'serverAuths');
}
}
);
};
$scope.resetAuth = function() {
$modalInstance.close();
};
}
}).result.then(
function() {
Auths.getAuthList().then(
function(resp) {
$scope.auths = resp;
}
);
}
);
Directive template:
<div class="alert-wrapper alert-{{ alert.type }}"
ng-repeat="alert in alerts"
ng-class="{ 'relative':relative }">
<div class="container">
<div alert type="alert.type" close="closeAlert($index)">{{alert.msg}}</div>
</div>
</div>
Directive code:
angular.module('app')
.directive('appAlerts', function() {
return {
restrict: 'A',
replace: true,
scope: {
watchForm: '=',
relative: '#'
},
templateUrl: 'partials/directives/appAlerts.html',
controller: function($scope, Alerts) {
$scope.closeAlert = function(idx) { Alerts.closeAlert(idx); };
$scope.alerts = Alerts.getAlerts();
}
};
});
Alerts Factory:
angular.module('app').factory('Alerts', function($timeout) {
var alerts = [];
function timeoutAlert(a) {
$timeout(function() {
a.splice(0, 1);
}, 2500);
}
var addAlert = function(type, msg) {
alerts.push({type:type, msg:msg});
timeoutAlert(alerts);
};
var closeAlert = function(index) {
alerts.splice(index, 1);
};
var getAlerts = function() {
return alerts;
};
var killAlert = function(msg) {
var alert = _.where(alerts, {msg:msg});
var idx = _.indexOf(alerts, alert[0]);
if (idx > -1) {
closeAlert(idx);
}
};
return {
addAlert:addAlert,
closeAlert:closeAlert,
getAlerts:getAlerts,
killAlert:killAlert
};
});