Angular popup with dynamic template and controller - angularjs

I have found the following code that produces a popup window.
angular.module('plunker', ['ui.bootstrap', 'myModal']);
angular.module("myModal", []).directive("myModal", function ($modal, $timeout) {
"use strict";
return {
template: '<div ng-click="clickMe(rowData)" ng-transclude></div>',
replace: true,
transclude: true,
scope: {
rowData: '&myModal'
},
link: function (scope, element, attrs) {
scope.clickMe = function () {
$modal.open({
template: "<div>Created By:" + scope.rowData().data + "</div>"
+ "<div class=\"modal-footer\">"
+ "<button class=\"btn btn-primary\" ng-click=\"ok()\">OK</button>"
+ "<button class=\"btn btn-warning\" ng-click=\"cancel()\">Cancel</button>"
+ "</div>",
controller: function ($scope, $modalInstance) {
$scope.ok = function () {
$modalInstance.close({ test: "test"});
};
$scope.cancel = function () {
};
$timeout(function () {
$(".modal-dialog").draggable();
var resizeOpts = {
handles: "all", autoHide: true
};
$(".modal-dialog").resizable(resizeOpts);
}, 0);
},
backdrop: "static"
});
}
}
};
});
I would like to make this code generic and assign templates and their controllers on the fly. I guess I could specify a template with controller built-in but want to avoid doing that.
Thanks

Related

Angular directive and controller

I have a directive and a controller. The directive as fallows:
calcP.directive('modalDialog', function() {
return {
restrict: 'E',
scope: {
show: '='
},
replace: true,
transclude: true,
link: function(scope, element, attrs) {
scope.dialogStyle = {};
if (attrs.width)
scope.dialogStyle.width = attrs.width;
if (attrs.height)
scope.dialogStyle.height = attrs.height;
**scope.hideModal = function() {
scope.show = false;
delete $sope.types.individual;**
};
},
template: "..."
};
});
My controller:
calcP.controller('calcPCtrl', function($scope, $http, $window, emailSenderEndpoint) {
$scope.getVariantDomovoy = function () {
$scope.types.domovoy = $scope.variants.domovoy;
};
$scope.getVariantIndividual = function () {
$scope.types.individual = $scope.variants.individual;
};
...
$scope.modalShown = false;
$scope.toggleModal = function() {
$scope.modalShown = !$scope.modalShown;
};
});
My template:
template: "<div class='ng-modal' ng-show='show'><div class='ng-modal-overlay' ng-click='hideModal()'></div><div class='ng-modal-dialog' ng-style='dialogStyle'><div class='ng-modal-close' ng-click='hideModal()'>X</div><div class='ng-modal-dialog-content' ng-transclude></div></div></div>"
I'd like to delete some $scope by adding it to a function. But the browser shows the error that it can't find the variable $scope.types.individual.
I just try to learnAangularJS by myself and still have some problems.
If you want to change a value of your controller from a directive, first you have to pass that variable to the directive with two way binding. Then you can change that value as below.
calcP.directive('modalDialog', function() {
return {
restrict: 'E',
scope: {
show: '=',
types: '='
},
replace: true,
transclude: true,
link: function(scope, element, attrs) {
scope.dialogStyle = {};
if (attrs.width)
scope.dialogStyle.width = attrs.width;
if (attrs.height)
scope.dialogStyle.height = attrs.height;
**scope.hideModal = function() {
scope.show = false;
scope.types.individual = "";**
};
},
template: "..."
};
});
Make sure you are passing your $scope.types from the controller to the directive. Same as you pass show parameter
May be like this,
<model-dialog show="show" types="types"></model-dialog>

angularjs nested cascading directive for dropdown

I want to create a cascading dropdown directive .
<my-dropdown label="states" url="http://statelisturl">
<my-dropdown label="cities" url="http://citylisturl">
</my-dropdown>
</my-dropdown>
But states will be list first, when I select a state cities will be get from url.
Is this possible for angularjs technically? Or I should be seperated directive for every dropdown?
You could do something like this:
.directive("myDropdown", function() {
return {
restrict: "E",
require: ["myDropdown", "?^^myDropdown"],
template: "<select ng-options='opt as opt.label for opt in $ctrl.options' ng-model='$ctrl.selectedOption' ng-change='$ctrl.changed($ctrl.selectedOption)'></select><div ng-transclude></div>",
scope: true,
bindToController: {
url: "#",
label: "#"
},
controller: function($scope, $http) {
var _self = this;
_self.init = function() {
$http.get(_self.url).then(function(response) {
_self.options = response.data;
});
}
_self.parentChanged = function(item) {
var id = item.id;
$http.get(_self.url + "?id=" + id).then(function(response) {
_self.options = response.data;
});
}
},
link: function(scope, element, attrs, ctrls) {
var ctrl = ctrls[0];
var parentCtrl = ctrls[1];
if (parentCtrl) {
scope.$watch(function() {
return parentCtrl.selectedOption;
}, function(newval) {
if (newval) {
ctrl.parentChanged(newval);
}
});
} else {
ctrl.init();
}
},
controllerAs: "$ctrl",
transclude: true
}
});
EDIT: I have a working example here

$scope.$watch not detecting changes in directive in same module

I'm implementing a watch in the controller, when user toggles a button. I have a watch inside the directive and that is working, e.g. it detects that the scope variable has changes but if I have a watch inside the controller it does not detects
<button toggle-button active-text="Yes" inactive-text="No" ng-model="light.state">Show millions</button><br>
here is the code:
'use strict';
angular.module('fiveYearOverview', ['fiveYearOverviewServices', 'fiveYearOverviewDirectives'])
.controller('fiveYearCtrl', [
'$scope', 'reports',
function ($scope, reports) {
//not working
$scope.$watch('lightState', function (newValue, oldValue) {
if (newValue)
console.log("I see a data change!");
}, true);
}
])
.directive('toggleButton', function () {
return {
require: 'ngModel',
scope: {
activeText: '#activeText',
inactiveText: '#inactiveText',
lightState: '=ngModel'
},
replace: true,
transclude: true,
template: '<div>' +
'<span ng-transclude></span> ' +
'<button class="btn" ng-class="{\'btn-primary\': state.value}" ng-click="state.toggle()">{{activeText}}</button>' +
'<button class="btn" ng-class="{\'btn-primary\': !state.value}" ng-click="state.toggle()">{{inactiveText}}</button>' +
'</div>',
link: function postLink(scope) {
scope.lightState = scope.inactiveText;
scope.state = {
value: false,
toggle: function () {
this.value = !this.value;
scope.lightState = this.value ? scope.activeText : scope.inactiveText;
console.log(scope.lightState);
//working
scope.$watch('lightState', function (newValue, oldValue) {
if (newValue)
console.log("I see a data change!");
}, true);
}
};
}
}
});
What is that i'm doing wrong ?
By defining a scope in the directive you are creating an isolated scope for it. Thats why you cant access its members from the controller.
lightState is being declared in a scope below that of fiveYearCtrl making it inaccessible as outlined here.
An alternative solution could be to define the callback function in fiveYearCtrl and call it from the directive.
.controller('fiveYearCtrl', [
'$scope', 'reports',
function ($scope, reports) {
this.consoleLog = function (newValue, oldValue) {
if (angular.isDefined(newValue))
console.log("I see a data change!");
};
}
])
link: function postLink(scope, element, attrs, ctrl)
{
scope.lightState = scope.inactiveText;
scope.state = {
value: false,
toggle: function () {
this.value = !this.value;
scope.lightState = this.value ? scope.activeText : scope.inactiveText;
console.log(scope.lightState);
//working
scope.$watch('lightState', ctrl.consoleLog, true);
}
};
}

Controller as with directive not working

I want to accomplish scroll-able content by clicking on Bootstrap module. Its working fine. This is following code of my directive:
'use strict';
angular.module('cbookApp')
.directive('scrollTo', scrollTo);
scrollTo.$inject = ['$anchorScroll'];
function scrollTo($anchorScroll) {
return {
restrict: 'A',
link: function (scope, element, attrs) {
element.bind('click', function (event) {
event.stopPropagation();
var location = attrs.scrollTo;
if (scope.vm.isEdit || typeof scope.vm.isEdit =="undefined" ) {
$anchorScroll(location);
} else {
$anchorScroll(location+'1');
}
});
}
};
}
But only problem is i am not sure how to apply active class to current affix li. This DEMO way i found to apply class active to current li and remove from other. It was working without Controller as but once i added controller as it stopped working and give some error of scope.
var app = angular.module('app', ['directives']);
app.controller('firstController',[function(){
var vm = this;
vm.model = { value: 'dsf'};
}]);
angular.module('directives', []).directive('toggleClass', function () {
var directiveDefinitionObject = {
restrict: 'A',
template: '<span ng-click="localFunction()" ng-class="selected" ng-transclude></span>',
replace: true,
bindToController: true,
scope: {
model: '='
},
transclude: true,
link: function (scope, element, attrs) {
scope.localFunction = function () {
scope.model.value = scope.$id;
};
scope.$watch('model.value', function () {
if (scope.model.value === scope.$id) {
scope.selected = "active";
} else {
scope.selected = '';
}
});
}
};
return directiveDefinitionObject;
});
Can you please add this in your directive.
element.parent().parent().children().each(function() {
$(this).find('a').removeClass('active');
});
element.addClass('active');
http://jsfiddle.net/hngzxmda/1/
I suggest using controllerAs in your directive too
angular.module('directives', []).directive('toggleClass', function () {
var directiveDefinitionObject = {
restrict: 'A',
template: '<span ng-click="vmd.localFunction()" ng-class="selected" ng-transclude></span>',
replace: true,
bindToController: {
model: '=',
$id: '='
},
scope: {},
transclude: true,
controller: function() {
var _this = this;
this.localFunction = function () {
_this.model.value = _this.$id;
};
},
controllerAs: 'vmd'
};
return directiveDefinitionObject;
});

how to call parent function controller from directive react component angularjs + reactjs?

I have angular application and we start using react as render data.we have one problem is how can we call $scope.showUserDetails from directive react component
.I tried using this.props.scope.$parent.showUserDetails(); I have Uncaught TypeError: Cannot read property '$parent' of undefined
react component
/** #jsx React.DOM */
var MYCOMPONENT = React.createClass({
displayName: 'MYCOMPONENT',
handleClick: function (e) {
console.log('You clicked');
this.props.scope.$parent.showUserDetails();
},
render: function (){
var listUser = this.props.data.map(function(item){
return(
React.DOM.div(
{
className: 'panel panel-default staff-reception ' + item.statusType.toLocaleLowerCase() + 'Office',
'ng-click': 'showUserDetails(' + item + ')',
onClick: this.handleClick
},
React.DOM.div(
{
className: 'panel-body'
},
React.DOM.span(null, item.firstName + ' ' + item.lastName + ' ' + item.directDial + ' Ext:' + item.voiceMailExt)
)
)
);
},this);
return (React.DOM.div({className:'col-xs-12 col-md-6 col-lg-4'}, listUser));
}
});
controller
(function () {
'use strict';
var app = angular.module('app');
var ReceptionReactController = function ($scope, ReceptionReactService, $modal) {
$scope.showUserDetails = function (user, index) {
var modalInstance = $modal.open({
templateUrl: 'UserDetails.html',
controller: UserDetailsController,
size: 'lg',
resolve: {
user: function () {
return user;
}
}
});
modalInstance.result.then(function (userUpdatedStatus) {
updateUserStatus(userUpdatedStatus);
}, function () {
});
};
};
app.controller('ReceptionReactController', ['$scope', 'ReceptionReactService', '$modal', '$window', ReceptionReactController]).directive('fastNg', function () {
return {
restrict: 'E',
scope: {
data: '='
},
link: function (scope, el, attrs){
scope.$watch('data', function(newValue, oldValue){
React.render(React.createElement(
MYCOMPONENT, {
data: newValue
}),
el[0]
);
});
}
}
});
}());
view
<fast-ng data="ListTitleUsers.users"></fast-ng>
It seems like you should pass the function you want through the directive's attributes and into the react component's props. Something like this might work:
<fast-ng data="ListTitleUsers.users" show="showUserDetails"></fast-ng>
-
app.controller('ReceptionReactController', ['$scope', 'ReceptionReactService', '$modal', '$window', ReceptionReactController]).directive('fastNg', function () {
return {
restrict: 'E',
scope: {
data: '=',
show: '='
},
link: function (scope, el, attrs){
scope.$watch('data', function(newValue, oldValue){
React.render(React.createElement(
MYCOMPONENT, {
data: newValue,
show: scope.show
}),
el[0]
);
});
}
}
});
-
handleClick: function (e) {
console.log('You clicked');
this.props.show();
},
-
onClick: this.handleClick.bind(this, item)

Resources