$scope.watch does not work between two different angular pages - angularjs

the below code is working within one page with different controlloers, but scope.watch does not work when I pass value from one page to another. How can you do that? below is my code.
.factory('Data', function () {
var data = {
LastName: '',
}
return {
getLastName: function () {
return data.LastName;
},
setLastName: function (lastname) {
data.LastName = lastname;
}
}
}
//FIRST CONTROLLER
$scope.lastname = '';
$scope.$watch('lastname', function (newValue2, oldValue2) {
if (newValue2 !== oldValue2)
Data.setLastName(newValue2);
});
//GET FIRST CONTROLLER INTO SECOND
$scope.$watch(function () {
return Data.getLastName();
}, function (newValue2, oldValue2) {
if (newValue2 !== oldValue2)
$scope.lastname = newValue2;
});
//form
//Firstcontroller
< input type = "text"
name="lastname"
placeholder = "Suhr"
ng-model="lastname"
ng-minlength="3" required />

Porting all your code and it works!
angular.module("test", [])
.controller('Test1', Test1)
.controller('Test2', Test2)
.factory('Data', Data);
function Test1($scope, Data) {
$scope.lastname = '';
$scope.$watch('lastname', function(newValue2, oldValue2) {
if (newValue2 !== oldValue2)
Data.setLastName(newValue2);
});
}
function Test2($scope, Data) {
$scope.$watch(function() {
return Data.getLastName();
}, function(newValue2, oldValue2) {
if (newValue2 !== oldValue2)
$scope.lastname = newValue2;
});
}
function Data() {
var data = {
LastName: '',
}
return {
getLastName: function() {
return data.LastName;
},
setLastName: function(lastname) {
data.LastName = lastname;
}
}
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.8/angular.min.js"></script>
<div ng-app="test">
<div ng-controller="Test1">
<input type="text" name="lastname" ng-model="lastname" placeholder="Suhr" ng-minlength="3" required>
</div>
<div ng-controller="Test2">
{{lastname}}
</div>
</div>

Related

How do I get ng-init to work with mutiple functions in a controller?

My html:
<div ng-app="APSApp" class="container">
<br />
<br />
<input type="text" placeholder="Search Terms" />
<br />
<div ng-controller="APSCtl" >
<table class="table">
<tr ng-repeat="r in searchTerms" ng-init="searchTerms=getSearchTerms()" >
<td>{{r.DisplayText}} <input type="text" ng-model="r.SearchInput"></td>
</tr>
</table>
</div>
</div>
<script type="text/javascript">
const moduleId = '#Dnn.ModuleContext.ModuleId';
const tabId = '#Dnn.ModuleContext.TabId';
</script>
<script src="/DesktopModules/RazorCart/Core/Content/Scripts/angular.min.js"></script>
<script src="/DesktopModules/MVC/AdvancedProductSearchMVC/Scripts/AdvancedProductSearch.js"></script>
My angular setup:
var aps = angular.module("APSApp", []);
aps.config(function($httpProvider) {
$httpProvider.defaults.transformRequest = function(data) {
return data !== undefined ? $.param(data) : null;
};
});
aps.factory('SearchTerms',
function($http) {
return {
getSearchTerms: function(onSuccess, onFailure) {
const rvtoken = $("input[name='__RequestVerificationToken']").val();
$http({
method: "post",
url: "/DesktopModules/MVC/AdvancedProductSearchMVC/AdvancedProductSearch/GetAPS",
headers: {
"ModuleId": moduleId,
"TabId": tabId,
"RequestVerificationToken": rvtoken
}
}).success(onSuccess).error(onFailure);
}
};
});
aps.controller('APSCtl',
function(SearchTerms, $scope) {
function getSearchTerms() {
$scope.searchTerms = [];
successFunction = function(data) {
$scope.searchTerms = data;
console.log($scope.searchTerms);
};
failureFunction = function(data) {
console.log('Error' + data);
};
SearchTerms.getSearchTerms(successFunction, failureFunction);
}
function doSomethingElse($scope) {}
});
I'm trying to create a single controller with multiple functions. This works if my angular controller looks like this (and I don't use ng-init):
aps.controller('APSCtl',
function(SearchTerms, $scope) {
$scope.searchTerms = [];
successFunction = function(data) {
$scope.searchTerms = data;
console.log($scope.searchTerms);
};
failureFunction = function(data) {
console.log('Error' + data);
};
SearchTerms.getSearchTerms(successFunction, failureFunction);
});
I was just trying to keep related functions in a single controller. What am I doing wrong? Do I actually have to set up a different controller for each function?
You do not have to assign the value in the template, you can just call the function,
<table class="table" ng-init="getSearchTerms()>
<tr ng-repeat="r in searchTerms" >
<td>{{r.DisplayText}} <input type="text" ng-model="r.SearchInput"></td>
</tr>
</table>
you should have a function named getSearchTerms() in your controller to get it called,
aps.controller('APSCtl',
function(SearchTerms, $scope) {
$scope.getSearchTerms() {
$scope.searchTerms = [];
successFunction = function(data) {
$scope.searchTerms = data;
console.log($scope.searchTerms);
};
failureFunction = function(data) {
console.log('Error' + data);
};
SearchTerms.getSearchTerms(successFunction, failureFunction);
}
function doSomethingElse($scope) {}
});

Scope from controller does not pass to directive

I have a html like this :
<div id="create-group" ng-controller="groupCreateController">
<div id="container">
<h1>Create group</h1>
<div class="row">
<div class="col-md-4"><input placeholder="Group Name.." ng-model="group.name"></div>
<div class="col-md-8">
<label>Group Description : </label>
<textarea ng-model="group.description"> </textarea>
</div>
</div>
<br/>
<div class="row">
<div class="col-sm-6">
<usermgr-permission-list group="group"></usermgr-permission-list>
<button type="button" class="btn btn-md btn-primary" ng-click="btnSave_click($event)">SAVE</button>
</div>
<div class="col-sm-6">
<usermgr-user-list group="group"></usermgr-user-list>
</div>
</div>
</div>
</div>
My controller is :
(function (module) {
'use strict';
module.controller('groupCreateController', function ($scope, $rootScope, $routeParams, $location, userGroupService, $mdDialog) {
$scope.group = [];
$scope.init = function () {
if ($routeParams.hasOwnProperty('id')) {
//edit mode
// $scope.trans.heading = 'Edit Release';
// $scope.trans.saveBtn = 'Save';
var id = parseInt($routeParams.id);
getUserGroup(id);
} else {
$scope.group[0].id = 0;
$scope.group[0].permissions = [];
$scope.assignedPermissions = [];
$scope.enrolledUsers = [];
$scope.group[0].users = [];
$scope.group[0].name = '';
$scope.group[0].description = '';
}
};
function getUserGroup(id) {
userGroupService.getbyid(id).then(function (info) {
if (info !== undefined && info.id === id) {
$scope.group[0].id = info.id;
$scope.group[0].name = info.name;
$scope.group[0].description = info.description;
console.log($scope.group);
// $rootScope.$broadcast('rCube-user-mgt-users-list', info.id);
// $rootScope.$broadcast('rCube-user-mgt-permissions-list', info.id);
}
else {
}
}).catch(function (exception) {
console.error(exception);
});
}
$scope.init();
});
})(angular.module('r-cube-user-mgt.user-group'));
I have two custom directives in the first block of code for user permissions and users. The group scope that i pass with the directive does not contain the values i put in the getUserGroup(id) function. The group name and group description shows up so the scope.group in the controller is filled, however thats not the case once i pass it to my directives. here is the directives code as well :
permissions list :
(function (module) {
'use strict';
module.directive('usermgrPermissionList', function () {
return {
restrict: 'E',
scope:{
group: '='
},
controller: function ($scope, permissionService) {
$scope.updatedPermissions=[];
console.log($scope.group); //it doesnt have the values from the controller ..
if (!$scope.group.hasOwnProperty('permissions')) {
$scope.group.permissions = [];
}
function getData() {
console.log("inside getDAta for permission list" + $scope.group.id;
permissionService.getPermissionsFiltered($scope.group.id).then(function (info) {
if (info && info.length > 0) {
console.log(info);
$scope.group.permissions = info.map(function (a, index, array) {
return {
id: a.id,
name: a.name,
description: a.description,
assigned: a.assigned
};
});
}
}).catch(function (exception) {
console.error(exception);
});
} //end of getData()
$scope.init = function () {
getData();
};
$scope.init();
},
templateUrl: 'r-cube-user-mgt/permission/list/list.tpl.html'
};
});
})(angular.module('r-cube-user-mgt.permission'));
can anyone help?
you cannot assign property to an array like this $scope.group.id = 0;
either make $scope.group object
$scope.group = {};
or add properties to an index
$scope.group = [];
$scope.init = function () {
if ($routeParams.hasOwnProperty('id')) {
//edit mode
// $scope.trans.heading = 'Edit Release';
// $scope.trans.saveBtn = 'Save';
var id = parseInt($routeParams.id);
getUserGroup(id);
} else {
$scope.group[0].id = 0;
$scope.group[0].permissions = [];
$scope.assignedPermissions = [];
$scope.enrolledUsers = [];
$scope.group[0].users = [];
$scope.group[0].name = '';
$scope.group[0].description = '';
}
};
So I solved the issue by adding broadcast to send the id when the directive loads. This worked!
in the Group controller i add broadcast and send the group.id
function getUserGroup(id) {
userGroupService.getbyid(id).then(function (info) {
if (info !== undefined && info.id === id) {
$scope.group.id = info.id;
$scope.group.name = info.name;
$scope.group.description = info.description;
console.log($scope.group);
$rootScope.$broadcast(rCubeTopics.userMgtPermissionLoadData, $scope.group.id);
}
}).catch(function (exception) {
console.error(exception);
});
}
and in the permission directive get that broadcast :
$scope.$on(rCubeTopics.userMgtPermissionLoadData, function (event, id) {
console.log($scope.group.id);
getData();
});

ng-show on a dircetives controller value

I am still learning angular and got this Problem:
Service Definition:
app.service('headService', function($window) {
this.display = 0;
return {
setTitle: function (newTitle) { $window.document.title = newTitle; },
setDisplay: function (value) { this.display = value;},
getDisplay: function () {
if(this.display===undefined){
this.display = 1;
}
return this.display
}
};
})
Controller Definition:
app.controller('startController', function(headService) {
headService.setTitle('by app 3');
this.isVisible = function () {
if(headService.getDisplay()===1){
return true;
} else {
return false;
}
}
});
directive implementation
app.directive("startDirective", function(headService) {
return {
restrict : "E",
templateUrl: 'app/templates/start.html',
controller: 'startController'
};
});
Now I would like to Show if the method this.isVisible Returns true
<div layout="column" flex>
<start-directive></start-directive>
<content-directive></content-directive>
<login-directive></login-directive>
</div>
which is included by
<body ng-controller="bodyController">
<application-directive layout="row" flex></application-directive>
</body>
But I can't get it running. Any hint?

Angular scope.watch not working in directive

I have a angular directive that watches a list, and then creates a custom select when the list is edited. I have this working on one page, but it refuses to work on another. I dont know why - but it looks like the watch is not catching when the list has changed.
I have reproduced the error here - http://codepen.io/jagdipa/pen/Ramjez - can someone please help?!
angular.module('MyApp',['ngMaterial', 'ngMessages', 'material.svgAssetsCache'])
.controller('AppCtrl', function($scope) {
$scope.clearValue = function() {
$scope.myModel = undefined;
};
$scope.save = function() {
alert('Form was valid!');
};
var Titles =[{"Title":"Mr"},{"Title":"Master"},{"Title":"Miss"},{"Title":"Mrs"}];
$scope.titles = Titles;
});
module MyApp.Directives {
interface TcSelectListScope extends ng.IScope {
sourceList: any[];
sourceListKey: string;
sourceListValue: string;
}
export class TcSelectListController {
static $inject = [];
constructor() {
}
}
export class TcSelectList {
public restrict = "A";
public require = ["ngModel", "^form", '^^mdInputContainer', "select"];
public controller = TcSelectListController;
public controllerAs = 'selectController';
public scope = {
sourceList: "="
}
constructor(private $compile: ng.ICompileService) {
}
public compile(tElement, tAttributes) {
var $compile = this.$compile;
var _cacheService = this.cacheService;
return function postLink(scope, element, attrs, controller) {
var ngModelCtrl = controller[0];
var mdInputContainerCtrl = controller[2];
var selectCtrl = controller[3];
console.log(selectCtrl);
/*if (scope.sourceList == undefined)
{
scope.sourceList = [];
}*/
scope.$watch(scope.sourceList, scope.onModelChanged, true);
//scope.$watchCollection(scope.sourceList, scope.onModelChanged);
scope.onModelChanged = () => {
console.log('tc select list directive 2');
console.log(scope.sourceList);
if (attrs.sourceListKey == undefined) {
throw ("The source-list-key needs to be defined for tc-select-list");
}
if (attrs.sourceListValue == undefined) {
throw ("The source-list-value needs to be defined for tc-select-list");
}
var html = undefined;
html = buildSelect();
html = markSelected(html);
element.append(html);
}
element.on("click", function () {
mdInputContainerCtrl.setHasValue(true);
});
element.bind("blur", function () {
if (ngModelCtrl.$viewValue == undefined) {
mdInputContainerCtrl.setHasValue(false);
}
});
element.bind("change", function () {
mdInputContainerCtrl.setHasValue(true);
});
function buildSelect() {
var html = ``;
angular.forEach(scope.sourceList, (val, index) => {
var itemKey = scope.sourceList[index][attrs.sourceListKey];
var itemValue = scope.sourceList[index][attrs.sourceListValue];
var selected = ``;
html += `<option label="` + itemValue +
`" value="` + itemKey +
`" ` + selected +
` >` + itemValue + ` < /option>`;
});
return html;
}
function markSelected(html) {
if (ngModelCtrl.$modelValue != undefined && ngModelCtrl.$modelValue != null) {
html = html.replace(`value="` + ngModelCtrl.$modelValue + `"`,
`value="` + ngModelCtrl.$modelValue + `" selected`)
}
return html
}
}
}
static factory() {
var directive = ($compile, cacheService) => new TcSelectList($compile, cacheService);
directive.$inject = ["$compile"];
return directive;
}
}
angular.module("MyApp").directive("tcSelectList", TcSelectList.factory());
}
<div ng-controller="AppCtrl" layout="column" layout-align="center center" style="min-height: 300px;" ng-cloak="" class="selectdemoValidations" ng-app="MyApp">
<form name="myForm">
<p>Note that invalid styling only applies if invalid and dirty</p>
<md-input-container class="md-block">
<label>Favorite Number</label>
<md-select name="myModel" ng-model="myModel" required="">
<md-option value="1">One 1</md-option>
<md-option value="2">Two</md-option>
</md-select>
<div class="errors" ng-messages="myForm.myModel.$error" ng-if="myForm.$dirty">
<div ng-message="required">Required</div>
</div>
</md-input-container>
<div layout="row">
<md-button ng-click="clearValue()" ng-disabled="!myModel" style="margin-right: 20px;">Clear</md-button>
<md-button ng-click="save()" ng-disabled="myForm.$invalid" class="md-primary" layout="" layout-align="center end">Save</md-button>
</div>
<md-input-container class="no-errors">
<label>{{translations["Title"]}}</label>
<div class="tc-select">
<select name="title"
tc-select-list
ng-model="myModel.Title"
source-list="titles"
source-list-key="Title"
source-list-value="Title"></select>
</div>
</md-input-container>
<br/>
{{titles}}
<br/>
Title = {{myModel.Title}}
</forms>
</div>
I found the answer. Turns out the following line doesnt work
scope.$watch(scope.sourceList, (newVal) => {
Changing it to the following sorted the problem out
scope.$watch('sourceList', (newVal) => {

Check/ Uncheck All checkboxes - AngularJS ng-repeat

I have a structure which looks like this: http://jsfiddle.net/deeptechtons/TKVH6/
<div>
<ul ng-controller="checkboxController">
<li>Check All
<input type="checkbox" ng-model="selectedAll" ng-click="checkAll()" />
</li>
<li ng-repeat="item in Items">
<label>{{item.Name}}
<input type="checkbox" ng-model="item.Selected" />
</label>
</li>
</ul>
</div>
angular.module("CheckAllModule", [])
.controller("checkboxController", function checkboxController($scope) {
$scope.Items = [{
Name: "Item one"
}, {
Name: "Item two"
}, {
Name: "Item three"
}];
$scope.checkAll = function () {
if ($scope.selectedAll) {
$scope.selectedAll = true;
} else {
$scope.selectedAll = false;
}
angular.forEach($scope.Items, function (item) {
item.Selected = $scope.selectedAll;
});
};
});
When check all is selected or deselected, all other checkboxes are selected. But when "Check All" is selected, and I deselect one of the items, I want "Check All" to be deselected.
Thanks in advance!
(PS: Thanks to deeptechtons for the JSFiddle)
If you are using Angular 1.3+ you can use getterSetter from ng-model-options to solve this and avoid manually keeping track of the allSelected state
HTML:
<input type="checkbox" ng-model="allSelected" ng-model-options="{getterSetter: true}"/>
JS:
var getAllSelected = function () {
var selectedItems = $scope.Items.filter(function (item) {
return item.Selected;
});
return selectedItems.length === $scope.Items.length;
}
var setAllSelected = function (value) {
angular.forEach($scope.Items, function (item) {
item.Selected = value;
});
}
$scope.allSelected = function (value) {
if (value !== undefined) {
return setAllSelected(value);
} else {
return getAllSelected();
}
}
http://jsfiddle.net/2jm6x4co/
You can use this function to check if all records are checked whenever a checkbox changes:
$scope.checkStatus= function() {
var checkCount = 0;
angular.forEach($scope.Items, function(item) {
if(item.Selected) checkCount++;
});
$scope.selectedAll = ( checkCount === $scope.Items.length);
};
The view code:
<input type="checkbox" ng-model="item.Selected" ng-change="checkStatus();"/>
http://jsfiddle.net/TKVH6/840/
working example: http://jsfiddle.net/egrendon/TKVH6/845/
view:
<input type="checkbox" ng-model="item.Selected" ng-click="setCheckAll(item)" />
controller:
angular.module("CheckAllModule", [])
.controller("checkboxController", function checkboxController($scope) {
$scope.Items = [{
Name: "Item one"
}, {
Name: "Item two"
}, {
Name: "Item three"
}];
$scope.checkAll = function () {
if ($scope.selectedAll) {
$scope.selectedAll = true;
} else {
$scope.selectedAll = false;
}
angular.forEach($scope.Items, function (item) {
item.Selected = $scope.selectedAll;
});
};
$scope.setCheckAll = function (item) {
//
// Check if checkAll should be unchecked
//
if ($scope.selectedAll && !item.Selected) {
$scope.selectedAll = false;
}
//
// Check if all are checked.
//
var checkCount = 0;
angular.forEach($scope.Items, function(item) {
if(item.Selected) checkCount++;
});
$scope.selectedAll = ( checkCount === $scope.Items.length);
};
});
Here is a neat little way of doing this
http://jsfiddle.net/TKVH6/850/
Use a little bit of undescore (just the reduce) and ng-checked
<input type="checkbox" ng-model="selectedAll" ng-click="checkAll()" ng-checked="allSelected()"/>
$scope.allSelected = function () {
var allSelect = _.reduce($scope.Items, function (memo, todo) {
return memo + (todo.Selected ? 1 : 0);
}, 0);
return (allSelect === $scope.Items.length);
};
You could use javascripts built in .reduce if you did not want to use underscore.
This answer has similar logic to Kmart2k1's answer. It puts the responsibility of updating the master checkbox on each child in the ng-repeat. Instead of using array.forEach, I use array.some to more quickly check if any of the items are unselected.
HTML:
<li ng-repeat="item in Items">
<label>{{item.Name}}
<input type="checkbox" ng-model="item.Selected" ng-change="notifyMaster()"/>
</label>
</li>
Javascript
$scope.notifyMaster = function () {
$scope.selectedAll = !$scope.Items.some(function (item) {
return !item.Selected; //check if ANY are unchecked
});
}
Forked fiddle

Resources