I have an interface with a "settings" button that opens a modal window. What I want to do is update scope values from the original controller. For example, in the MainController, i define a "default" theme that is used to control the theme in the body tag.
$scope.theme = 'default';
In the controller, I am updating the value of $scope.theme from an input in the view with something like ng-click"changeTheme(newValue)" .. which updates $scope.theme and furthermore, the body's class is reflected by this value.
<body ng-controller="MainController" ng-class="{midnight: theme == 'midnight'}">
Here is the modal code in that controller
$scope.open = function (settings) {
$scope.settings = settings;
$modal.open({
templateUrl: 'myModalContent.html',
backdrop: true,
windowClass: 'modal',
controller: function ($scope, $modalInstance, settings) {
$scope.settings = settings;
$scope.submit = function () {
$modalInstance.dismiss('cancel');
}
},
resolve: {
settings: function () {
return $scope.settings;
}
}
});
};
And in the view ... here's what I have so far.
<script type="text/ng-template" id="myModalContent.html">
<form ng-submit="submit()">
<div class="modal-body">
<label>Label</label>
<input type="text" ng-model="settings.label" />
<label>Value</label>
<input type="text" ng-model="settings.theme" />
</div>
<div class="modal-footer">
<input type="submit" class="btn primary-btn" value="Close" />
</div>
</form>
</script>
This example works when sending back anything that is created in this new $scope.settings object. But what I want is for the new settings object to update the $scope.theme from the main controller as well. What am I missing?
The problem was I didn't give UI bootstrap nearly enough attention with their basic example. All I wanted was to find a way for the selection in the modal to update various scope values on the page. I've figured out out by messing with this example:
http://plnkr.co/edit/jpJX4WvHw0SSYm3pAAzq?p=preview
My trouble was understanding how to handle multiple variables changing from the modal. This is a very simple fork that illustrates what I was trying to initially understand:
http://plnkr.co/edit/RYNcURKjGhWxUBpUlAkD?p=preview
Related
I have converted one of my Angular controllers to Controller As syntax, but I am having trouble getting an ng-grid template to play nicely.
The controller has a function called edit user that looks like this
self.editUser = function (user_data) {
var modalInstance = $modal.open({
templateUrl: '/admin/views/adminuser.html',
controller: 'AdminUserController',
resolve: {
user_data: function () {
return user_data;
}
}
});
modalInstance.result.then(function () {
self.myQueryData.refresh = !self.myQueryData.refresh;
});
};
the ng-grid template looks like this
<div class="ngCellText" ng-class="col.colIndex()">
<a ng-click="$parent.$parent.$parent.$parent.editUser({user_id:row.entity.id, first_name:row.entity.first_name, last_name:row.entity.last_name, email:row.entity.email})">
<span ng-cell-text translate>Edit</span>
</a>
</div>
and my route looks like this
.when('/admin/settings', {
templateUrl: '/admin/views/settings.html',
controller: 'SettingsController as sc',
})
So the problem is in the template when I call
$parent.$parent.$parent.$parent.editUser
it doesn't know what I am talking about unless I include the controller name like
$parent.$parent.$parent.$parent.sc.editUser,
then it works great. However I don't want to bind this template directly to the sc controller. How can I call the editUser without using the controller name?
I was hoping there would be a function on the $parent that would supply the function name like
$parent.$parent.$parent.$parent.getController().editUser
Any suggestions?
You can call functions on parent scope directly without referring to $parent. Because you might get in to trouble later when you modify your view structure.
example:
<div ng-app="MyApp">
<div ng-controller="MyController">
{{myMessage}}
<div ng-controller="MyController2">
<div ng-controller="MyController3">
<div ng-controller="MyController4">
<button id="myButton" ng-click="setMessage('second')">Press</button>
</div>
</div>
</div>
<script>
angular.module('MyApp', [])
.controller('MyController', function($scope) {
$scope.myMessage = "First";
$scope.setMessage = function(msg) {
$scope.myMessage = msg;
};
}).controller('MyController2', function($scope) {
}).controller('MyController3', function($scope) {
}).controller('MyController4', function($scope) {
});
</script>
</div>
</div>
Or else you can use angular $broadcast
Since you are using controllerAs syntax, you can address your controller by the alias, so the actual template line will look like this:
<a ng-click="sc.editUser({user_id:row.entity.id, first_name:row.entity.first_name, last_name:row.entity.last_name, email:row.entity.email})">
Consider two div areas as follows, in html file
<div class="divArea1" ng-controller="myController">
<input ng-click="updateName()" type="button" value="button"/>
</div>
<div class="divArea1" ng-controller="myController">
<p>{{name}}</p>
</div>
Following is the angular js example
productApp.controller("myController", [ '$scope', function($scope) {
$scope.name= "XYZ";
$scope.updateName= function() {
$scope.name = "ABC";
};
} ]);
problem is when I am trying to update the name, upon click on update button it is not visible in the second in the div area. Is there any mistake i am doing.
What you have is two different controllers (with two separate scopes) with the same name.
You need to put the controller in the parent controller to keep the name in the same scope as the button:
<div id="container" ng-controller="myController">
<div class="divArea1">
<input ng-click="updateName()" type="button" value="button"/>
</div>
<div class="divArea1">
<p>{{name}}</p>
</div>
</div>
Controllers are not singletons. Each time you have a new controller, you're having a new instance of this controller, with a new isolated scope.
If your need is to share data between controllers, you should use a factory (which is a singleton).
angular.module('app').factory('mySharedData', function(){
var service = {
object : objectToShare
};
var objectToShare = {};
return service;
});
And from your controller :
angular.module('app').controller('myController',
['$scope','mySharedData',
function($scope, mySharedData){
$scope.someObject = mySharedData.object;
$scope.updateName= function() {
$scope.someObject.name = "ABC";
};
}
]);
And from your view :
<div class="divArea1" ng-controller="myController">
<input ng-click="updateName()" type="button" value="button"/>
</div>
<div class="divArea1" ng-controller="myController">
<p>{{someObject.name}}</p>
</div>
Note : I've encapsulated the name property into an object because objects are passed by reference, and strings by value. This allows you to make it easier to share your values and to have it automatically updated into the service and other controllers, without having to access your property through accessors.
here is demo http://jsfiddle.net/wg7pb1yu/3/
inject $rootScope so that it will do from global scope
productApp.controller("myController", [ '$scope','$rootScope', function($scope, $rootScope) {
$rootScope.name= "XYZ";
$scope.updateName= function() {
$rootScope.name = "ABC";
};} ]);
Hope this will help you
I have a single kendo-window in my page and i want to load content to it every time i click a command. The content i want to load is either from x-kendo-template or from .html with expression in angular {{Sample}}. After the content is loaded, i tried to $compile the content to make use of the angular binding but it is not working. This is what i tried so far
On my markup
<base href="http://demos.telerik.com/kendo-ui/grid/angular">
<script id="tplAddNew" type="text/x-kendo-template">
Action in Add New: {{ Action }}
</script>
<script id="tplView" type="text/x-kendo-template">
Action in View: {{ Action }}
</script>
<div id="example" ng-app="Test">
<div ng-controller="MyCtrl">
<div kendo-window="winTesting"
k-visible="false"
k-modal="true"
k-pinned="true"
k-width="'500px'"
k-min-height="'200px'">
</div>
<button
kendo-button
ng-click="AddEntry()">Add Entry</button>
<button
kendo-button
ng-click="ViewContent()">View Content</button>
</div>
</div>
and here is my controller
var app = angular.module("Test", ["kendo.directives"]);
app.controller("MyCtrl", [
"$scope", "$compile",
function($scope, $compile) {
$scope.AddEntry = function() {
$scope.Action = "Add New";
$scope.winTesting
.refresh({
//url: '../References/Test-entry.html'
template: kendo.template($('#tplAddNew').html())
})
.setOptions({
title: "Create New User"
});
//$scope.$apply(function() {
// $compile($scope.winTesting.element)($scope);
//});
$scope.winTesting.open().center();
}
$scope.ViewContent = function() {
$scope.winTesting
.refresh({
//url: '../References/View-entry.html'
template: kendo.template($('#tplView').html())
})
.setOptions({
title: "View User Detail"
});
//$scope.$apply(function() {
// $compile($scope.winTesting.element)($scope);
//});
$scope.winTesting.open().center();
}
}
]);
lets assume that the content of Test-entry.html is the same as tplAddNew Template
Now, when i will use the $compile function, it will show an error of $apply already in progress
Any help would be appreciated. TIA
i also prepared a JSFiddle
Kendo has not really refined this widget yet. So in light of that use the $timeout service:
$timeout(function() {
$compile($scope.winTesting.element)($scope);
}, true);
The last boolean parameter does (more or less) a $scope.$apply. See the Documentation
Edit:
There is also some cool stuff you could do with the $parse service as well. You might find it useful as explained in this blog
I'm new to Angular.
I am having problems dealing with variables back and forth between my controller and html.
In my controller not only I want to read $scope, but I also want to use it in a function I have in my services.
This is my factory:
angular.module('myApp.services', [])
.factory('hotels', function($http){
return{
search: function(city, callback){
$http({
method: 'GET',
url: 'http://myhotels.com/hotels/?city='+city+
cache: true
}).success(callback);
}
};
})
controller:
angular.module('myApp.controllers', [])
.controller('SearchHotelsController', ['$scope', 'hotels', function($scope, hotels){
$scope.hotelCity = "";
hotels.search($scope.hotelCity, function(hotelResults){
$scope.hotelResults = hotelResults;
});
}])
and in the html I don't have a button to call the function. It is supposed to be called when I get the scope variable (hotelResults):
<input class="form-control" type="text" ng-model="hotelCity">
<a ng-href="#/searchResults"><button>Search</button></a>
and when it routes to that page, which uses the same controller, I get:
{{hotelResults.name}}
================================================================
I also tried declaring $scope.hotels = {hotelCity: "sf"}; in th controller , then put this in html: <input type="text" ng-model="hotels.hotelCity"> and in my controller to call $scope.hotels.hotelCity in the function, but still they are not connected! no matter what the user puts in the input, I get 'sf' for my hotelCity.
Please someone shed a light on this for me, thanks!
I am also new-bie to angular, and looking at your question, i am not fully aware what you are actually looking for but what i have understood and came up with this. Might help.
<html ng-app="myApp">
<head><title>Test</title>
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.2.21/angular.min.js"></script>
</head>
<body>
<div class="test-wrap" ng-controller="myHotels">
<input type="text" name="h" ng-model="hotelcity" />
<button ng- click="search()">Search</button>
<p>List of Hotel's</p>
<ul>
<li ng-repeat="h in hotel | filter:hotelcity">{{h.name}}</li>
</ul>
</div>
</body>
</html>
<script type="text/javascript">
var myApp = angular.module('myApp',[]);
myApp.controller('myHotels', ['$scope', function($scope) {
$scope.hotel = [{"name":"Test1 hotel"},{"name":"Test2 hotel"},{"name":"Test3 hotel"}];
$scope.search = function(){
console.log($scope.hotelcity);
}
}]);
</script>
I finally decided to pass my data through my url and then get it with $routeParams in my controller.
I didn't figure out the problem with my code, and I kind of expected Angular to be this smooth with passing variables back and forth, but I guess this particular situation is a javascript issue with different scopes and function arguments.
I also learned about the Closure concept of javascript which didn't help me either!
Solution: I put a button at the bottom of the page inside an tag;
<a ng-href="#/searchResults/{{hotelCity}}"><button>Search</button></a>
then in routeProvide in my app.js file:
$routeProvider.when('/searchResults/:city', {templateUrl: 'partials/second.html', controller: 'secondController'});
then in controller:
hotels.search($routeParams.city, function(hotelResults){
$scope.hotelResults = hotelResults;
});
[make sure to declare $routeParams in your controller next to $scope]
I have a model that I want to be editable, but for some reason nothing change, the textbox doesn't show up and the model is not being updated when using ng-view.
I can see the function enableEditor() being called using console.log.
If I write it inline instead of ng-view in the index.html without the profile.html everything works perfectly.
here are the files:
app.js
var proGamersApp = angular.module('proGamersApp', ['ngResource']).
config(function ($routeProvider) {
$routeProvider.
when('/', { controller: 'ProfileController', templateUrl: '/app/partials/profile.html' }).
otherwise({ redirectTo: '/' });
});
var ProfileController = function ($scope) {
$scope.init = function () {
$scope.title = 'first title';
};
$scope.init();
$scope.enableEditor = function () {
console.log('enableEditor()')
$scope.editorEnabled = true;
$scope.editableTitle = 'second title';
$scope.title = 'second title';
};
...
};
index.html
<!doctype html>
<html ng-app="proGamersApp">
<head>
<title>Pro Gamers</title>
<!-- Scripts -->
<script src="/app/lib/angular.min.js"></script>
<script src="/app/lib/angular-resource.js"></script>
<script src="/app/app.js"></script>
</head>
<body>
<div ng-view></div>
</body>
</html>
profile.html
<div ng-hide="editorEnabled">
{{title}}
Edit title
</div>
<div ng-show="editorEnabled">
<input ng-model="title" ng-show="editorEnabled">
Save
or
cancel.
</div>
Does someone know what I am doing wrong?
thanks
The link is adding to your address, causing the router to refresh the page and wack all your $scope vars. Instead of using blank anchors, use a span styled like an anchor:
span:hover {
cursor:pointer;
}
This only gives the cursor the pointer finger, customize the colors as you wish. Per your comments as well, don't add the target=_self to the href, add it after:
Save //prevent address bar change
As I said before though, use spans instead.