pass parameters to angular js directive partial view - angularjs-directive

I have an MVC application using angularJS. I have a primary navigation and secondary navigation. I am using ngRoute for primary navigation. I made secondary navigation template a directive that I can use in all the other pages. The template used in the directive needs some input parameters.
Routing code:
myApp.config(['$routeProvider', function ($routeProvider) {
$routeProvider.
when('/SecondaryNavigation/1', {
templateUrl: 'administration/Page1',
resolve: {
SecNavItems: ["$http", function($http){
var navItems = $http.get('/Navigation/SecondaryNavigation', {params: { pageName: 'Administration'}});
navItems.success(function (data) {
return data;
});
}]
},
controller: 'AdminController'
})}]);
var AdminController = function ($scope, SecNavItems) {
$scope.secList = SecNavItems;
}
AdminController.$inject = ["$scope", "SecNavItems"];
myApp.controller("AdminController", AdminController);
Web method code:
[HttpGet]
public JsonResult SecondaryNavigation(string pageName)
{
Dictionary<string, string> secnavItems = new Dictionary<string, string>();
secnavItems.Add("1", "Item1");
secnavItems.Add("2", "Item2");
var navigationItemsJson = Json(secnavItems, JsonRequestBehavior.AllowGet);
return navigationItemsJson;
}
Page1 code is
<secondary-navigation></secondary-navigation>
My directive is defined as follows:
myApp.directive("secondaryNavigation", function () {
return {
restrict: 'E',
scope: {},
templateUrl: '/navigation/secondaryNavigation'
}
});
Partial view template:
<div style="height:100%; width:25%; background-color:#675c5c; color: white; float:left">
#foreach (KeyValuePair<int, string> navItem in secList)
{
#navItem.Value<br /><br />
}
</div>
<div style="height:100%; width:75%; float:right"></div>
When I run the application I do not see the Item1 and Item2 in the page instead I see {{object}}
Please advise what I am missing in passing the parameters to the template used in the directive.
Thank you.

Figured what went wrong.
I had to create a html template of secondary navigation. I then included the web service call in the admincontroller, set the object value to the webservice result and added it to the routeProvider. I then
set the scope to false in the directive.
Following are the changes I made.
Routing code:
myApp.config(['$routeProvider', function ($routeProvider) {
$routeProvider.
when('/SecondaryNavigation/1', {
templateUrl: 'administration/Page1',
controller: 'AdminController'
})}]);
var AdminController = function ($scope, $http) {
var navItems = $http.get('/Navigation/SecondaryNavigation', {params: { pageName: 'Administration'}});
navItems.success(function (data) {
$scope.secList = data;
});
}]
},
}
AdminController.$inject = ["$scope", "$http"];
myApp.controller("AdminController", AdminController);
My directive is defined as follows:
myApp.directive("secondaryNavigation", function () {
return {
restrict: 'E',
scope: false,
templateUrl: '/navigation/secondaryNavigation'
}
});

Related

Needed factory working in angular js

Actually i was new to angular js i am trying to call my factory operation into controller i dont know where i am going wrong
and my js goes here
app.factory("myFactory",function(){
var something = {};
something.getsum = function() {
$scope.service = " heloo people"
}
return something;
});
app.controller("helloController", function($scope,myFactory) {
$scope.clickme = function() {
$scope.service=myFactory.getsum();
}
});
and my html goes here
<div ng-controller="hello controller">
<button ng-click="clickme"></button>
<h2>{{service}}</h2>
</div>
and my config goes here:
$urlRouterProvider.otherwise("/index/utilise");
$stateProvider
.state('index', {
abstract: true,
url: "/index",
templateUrl: "display.html",
controller:'mainController',
controllerAs: "parentCtrl",
})
.state('index.sample', {
url: "/home",
templateUrl: "content/sample.html",
})
.state('index.utilise', {
url: "/utilise",
templateUrl: "content/utilise.html",
})
})
First issue is that to use the myFactory factory in your controller you would need to inject it into the controller via dependency injection:
app.controller("helloController", function($scope, myFactory) {
$scope.clickme = function() {
$scope.service = myFactory.getsum();
}
});
Second issue you would not use $scope in the myFactory factory method getsum(), you would simply return the value you need:
app.factory("myFactory",function(){
var something = {};
something.getsum = function() {
return " heloo people";
}
return something;
});
Third issue is ng-click was not actually execute controller function clickme as there was parenthesis () as you would with any JavaScript function. It should be ng-click="clickme()" to actually call the function on the controller:
<div ng-controller="helloController">
<button ng-click="clickme()"></button>
<h2>{{service}}</h2>
</div>
Finally, it's unclear what the structure of your application based on the ui-router configuration your provided. With ui-router you wouldn't really have the need to use ng-controller as you can specify what controller any given view should be using. I've created multiple Plunkers, one and two, demonstrating the factory functionality with and without controllers specified for child routes. This should be more than enough to demonstrating calling a controller function in different situations.
Hopefully that helps!

Testing angular component's controller with Jasmine

This is my component:
const comp = {
controller: 'gridDetailsNavigationCtrl',
controllerAs: '$ctrl',
templateUrl: '/Scripts/app/shared/grid/navigation/gridDetailsNavigation.html',
bindToController: true,
bindings: {
viewData: '<',
listState: '#',
detailsState: '#',
pagingData: '=',
backSpinnerId: '#',
stateParams: '<'
}
};
This is part of the component's controller:
class GridDetailsNavigation {
constructor($rootScope, $scope, $state, tipaltiConsts) {
this._$state = $state;
this._$scope = $scope;
this._$rootScope = $rootScope;
this._consts = tipaltiConsts;
}
$onInit() {
....
}
$onDestroy() {
...
}
goToNext() {
....
}
goToPrev() {
....
}
}
I'm trying to test the component and its controller. I'm able to create a component and even get its controller scope:
const component = compile(angular.element(template))(scope);
scope.$digest();
component.$onInit();
// get controller in two different ways.
const $ctrl = component.scope().$ctrl;
const $ctrl2 = component.controller('gridDetailsNavigationCtrl');
My problem is that the $ctrl returns only scope properties and public methods e.g goToNext and goToPrev are not defined, and $ctrl2 is undefined.
I know I can use $componentController but I want the component itself and from it to get the controller. What am I doing wrong here? Why are methods unreachable? why is the second controller undefined?
Thanks

Dynamic ui-sref in directive template Angular Js

In my angular js Application, I have a directive inside a ng-repeat. Directive has a template in which the HTML part is loaded. Inside that template I am declaring a ui-sref Router dynamically setting states!
This does not Work!
I have tried a Fiddle
Without using a Directive ui-sref works Fine. But I need it in Directive's template.
MY HTML PART
<div ng-repeat="sp in obj.PEs">
<div draw-pe proc="{{sp.peId}}"></div>
</div>
<div style="border:1px;" ui-view="properties"></div>
My Script Part
var myApp = angular.module('myApp', ["ui.router"]);
myApp.controller("testCtrl", function($scope) {
$scope.obj = {
"PEs": {
"1": {
"peId": "1",
"peName": "Exp1",
"peDisplayName": "Exp",
"peType": "Exp",
"peCategory": "PE"
},
"2": {
"peId": "2",
"peName": "RN1",
"peDisplayName": "RNull",
"peType": "RN",
"peCategory": "PE"
}
}
}
})
myApp.config(function($stateProvider, $urlRouterProvider) {
$urlRouterProvider.otherwise('/');
$stateProvider
.state('Exp', {
url: '/Exp/:peId',
views: {
"properties": {
template: ".<h3>I am Exp ! </h3>",
controller: function($scope, $stateParams) {
var peId = $stateParams.peId;
alert("Peid-> " + angular.toJson($scope.obj.PEs[peId]));
}
}
}
})
.state('RN', {
url: '/RN/:peId',
views: {
"properties": {
template: "<h3> I am RN ! </h3>",
controller: function($scope, $stateParams) {
var peId = $stateParams.peId;
alert("Peid-> " + angular.toJson($scope.obj.PEs[peId]));
}
}
}
})
});
myApp.directive("drawPe", function() {
return {
restrict: "AE",
template: '<div ui-sref="{{peObj.peType}}( { peId:peObj.peId } )"> <h5>{{peObj.peDisplayName}}</h5></div>',
link: function($scope, element, attrs) {
var procId = $scope.$eval(attrs.proc);
alert(procId);
// alert(angular.toJson(scope.obj.processElements[procId]))
$scope.peObj = $scope.obj.PEs[procId];
}
}
})
See the Browser Console, on clicking the output Part!
ERROR
Error: Invalid state ref '( { peId:peObj.peId } )'
What will be the best Practice to call dynamic state names inside directives Template? I Have read some previous asked question and answer, But I am not clear with the idea as I am new to Angular Js.
Any Idea/help appreciated
Thanks
You can use $compile service to compile your directive's template when your scope changes.
Your directive could look like this:
myApp.directive("drawPe", function($compile) {
return {
restrict: "AE",
tranclude: true,
scope: {
peObj: '='
},
template: ' <h5>{{peObj.peDisplayName}}</h5>',
link: function(scope, element, attrs) {
console.log(scope.peObj);
scope.$watch(
function(scope) {
// watch the 'compile' expression for changes
//return scope.$eval(attrs.compile);
},
function(value) {
$compile(element.contents())(scope);
}
);
}
}
});
And your html:
<div ng-repeat="sp in obj.PEs">
<div draw-pe pe-obj="sp" proc="{{sp.peId}}"></div>
</div>
<div style="border:1px;" ui-view="properties"></div>
Working fiddle is here.

Launching modal on parent from a directive

I have a view with a ui.bootstrap modal that has its own controller.
In the view, i have a directive that generates a number of buttons with a unique ID.
I want to be able to click on one of the buttons generated and call the main view's controller to launch the modal.
Here is the main view module:
/* global angular */
angular.module('my.jobs', [
'ui.router',
'ui.bootstrap'
])
.controller('DashboardJobsCtrl', function DashboardJobsController($rootScope, $scope, $log, $state, $modal) {
var self = this;
angular.extend(this, {
displayReceipt: function(jobId) {
var modalInstance = $modal.open({
animation: true,
templateUrl: 'receiptModal.html',
size: 'lg',
controller: function($scope, $modalInstance, jobsService) {
//CODE HERE FOR ADDING VALUES TO THE MODAL...
$scope.clear = function() {
$modalInstance.close();
};
}
});
}
});
});
Here is the directive:
angular.module('jobView', ['ui.router', 'ui.bootstrap'])
.directive('jobView', function($compile, $http, $templateCache, DOMAINS) {
return {
restrict: 'E',
scope: {
job: '=',
view: '#'
},
template: 'myTemplate.html',
link: function($scope, element, attrs) {
//ASSUME THERE IS CODE HERE FOR GENERATING UNIQUE ID FOR JOBS
//NEXT LINE I WANT TO CALL MODAL FROM THE MAIN VIEW MODULE
$scope.displayReceipt('jobId')
}
};
});
I know this is a simple scope issue, but it's driving me nuts that I can't make the connection.
Here is the perfect example. calling method of parent controller from a directive in AngularJS.
I have update your example below.
<job-View updateParent='displayReceipt()'></job-View>
angular.module('jobView', ['ui.router', 'ui.bootstrap'])
.directive('jobView', function($compile, $http, $templateCache, DOMAINS) {
return {
restrict: 'E',
scope: {
job: '=',
view: '#',
updateParent:'&'
},
template: 'myTemplate.html',
link: function($scope, element, attrs) {
//ASSUME THERE IS CODE HERE FOR GENERATING UNIQUE ID FOR JOBS
//NEXT LINE I WANT TO CALL MODAL FROM THE MAIN VIEW MODULE
$scope.displayReceipt('jobId')
}
};
});

How to pass data between pages in Ionic app

I have had a look at all the examples around and tried to integrate with my Ionic project and failed. Here is what I have so far.
I am using a project created using creator.ionic.com
I have an html page that im loading a JSON file into
(agentSchedule.html)
<ion-view style="" title="Agent Schedule">
<ion-content class="has-header" overflow-scroll="true" padding="true">
<ion-refresher on-refresh="doRefresh()">
</ion-refresher>
<div ng-controller="agentScheduleCtrl">
<ion-list style="">
<ion-item class="item-icon-right item item-text-wrap item-thumbnail-left" ng-repeat="user in users">
<img ng-src="{{ user.image }}">
<h2>{{ user.fname }} {{ user.lname }}</h2>
<h4>Role : {{ user.jobtitle }}</h4>
<h4>Username : {{ user.username }}</h4><i class="button-icon icon ion-ios-arrow-forward"></i>
</ion-item>
</ion-list>
</div>
</ion-content>
Here is the controller and routes for that page
.controller('agentScheduleCtrl', function($scope, $http, $timeout) {
var url = "http://www.otago.ac.nz/itssd-schedule/mobileappdevice/services/getUsers.php";
var url = "users.json";
$http.get(url).success( function(response) {
$scope.users = response;
});
.state('menu.agentSchedule', {
url: '/page4',
views: {
'side-menu21': {
templateUrl: 'templates/agentSchedule.html',
controller: 'agentScheduleCtrl'
}
}
})
I am another page that I want to pass the username to, and then use on any page that I go from there
(specificAgentDetails.html)
<ion-view style="" view-title="Agent Specific Schedule">
<ion-content class="has-header" overflow-scroll="true" padding="true">
</ion-content>
</ion-view>
Here is the controller and routes for that page
.controller('specificAgentDetailsCtrl', function($scope) {
})
.state('menu.specificAgentDetailsCtrl', {
url: '/page9',
views: {
'side-menu21': {
templateUrl: 'templates/specificAgentDetailsCtrl.html',
controller: 'specificAgentDetailsCtrl'
}
}
})
How to Pass the user.username JSON variable to the next page as a global variable ??
Any help would be awesome - im going around in circles
So what #shershen said is true most ionic apps are set up as SPA's, what you're going to do isn't a "ionic" thing it's more of a AngularJS thing. You're going to want to setup a Service to hold your User info and then share it with your other controllers.
Create a Factory to share the data.
Inject the factory into the first controller and set it.
Inject the factory into the second controller and retrieve it.
Share data between AngularJS controllers
If you're familiar with get/set in OOP you should have no problem.
.factory('Data', function () {
var user = {};
return {
getUser: function () {
return user;
},
setUser: function (userparameter) {
user = userparameter;
}
};
})
.controller('agentScheduleCtrl', function($scope, $http, $timeout, Data) {
var url = "http://www.otago.ac.nz/itssdschedule/mobileappdevice/services/getUsers.php";
var url = "users.json";
$http.get(url).success( function(response) {
Data.setUser(response);
$scope.users = response;
});
Then in your second controller:
.controller('specificAgentDetailsCtrl', function($scope, Data) {
$scope.user = Data.getUser();
})
Make sure the syntax between the view and controllers are correct. I'm using user you're using users, setup breakpoints in your controllers to see what's going on there.
I use a little generic factory to do the job.
.factory('LocalRepo', function () {
var data = {}
return {
Get: function (key) {
return data.key;
},
Set: function (key, val) {
return data.key = val;
}
}
})
.controller('One', function($scope, LocalRepo) {
//Set in first controller
//TODO: $scope.users = .... from your call
LocalRepo.Set('users', $scope.users);
})
.controller('Two', function($scope, LocalRepo) {
//Get in second controller
$scope.users = LocalRepo.Get('users');
})
Use it to set whatever you want between controllers
Here is a quite simple solution. use $window and it will hold the data globally available for all controllers, services or anything etc.
.controller('agentScheduleCtrl', function($scope, $http, $timeout,$windows) {
$window.users = [];
var url = "http://www.otago.ac.nz/itssd-schedule/mobileappdevice/services/getUsers.php";
var url = "users.json";
$http.get(url).success( function(response) {
$window.users = response;
});
})
Inject $window as dependency in other controller and you can access it like $window.users.
Hope it helps someone.