AngularJS change Page title from view - angularjs

I got an index.html page with the following code
<html>
<head>
<title>{{title}}</title>
</head>
</html>
And i got a view.html
<div ng-controller="changeCtrl">
<input type="text" ng-model="page-title">
</div>
The routing works perfectly,
Now how can i bind the page-title model to the {{title}} while i type?
Thanks

To avoid using $rootScope or moving ng-app, use a service to handle setting the page title. In the snippet below I've given an example of using a service.
angular.module('app', [])
.service('PageService', function($window) {
return {
setTitle: function (newTitle) { $window.document.title = newTitle; }
};
})
.controller('ChangeCtrl', function(PageService) {
this.setPageTitle = PageService.setTitle;
});
<html>
<head>
<title>My Awesome App</title>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
</head>
<body ng-app="app">
<div ng-controller="ChangeCtrl as ctrl">
<label>{{ctrl.title}}</label>
<input type="text" ng-model="ctrl.title" ng-change="ctrl.setPageTitle(ctrl.title)">
</div>
</body>
</html>

First of all, since the expression is right under the html root element, the angular application must "cover" this element. So ng-app should be on the html element:
<html ng-app="app">
Second, since the expression is outside of any controller scope, angular looks for the title field in the $rootScope. So, you need your input field, inside a view handled by a controller, to modify the value of a $rootScope attribute.
That can't be done:
<input ng-model="title" />
will set the field titleon the controller scope. What can be done, though, is to access an object, by scope inheritance, defined in the root scope, and modify one of its attributes. So, firstmake sure such an object exists in the root scope:
angular.module('app').run(function($rootScope) {
$rootScope.page = {
title: 'default title'
};
});
Then change the expressions to access the title attribute of this object:
<title>{{ page.title }}</title>
and in the controller view:
<input ng-model="page.title" />

make all your data bindings inside ng-controllers scope, that is {{title}} should inside or you move to your ng-controller to html tag, :)

Related

angular js dynamic directive passing model attribute

I knwo that are many relevant posts about how creating dynamic directive mapping in angular but I cannot find anything similar in my case. As the description suggests I am trying to make a dynamic directive where depending the value of an object attribute the html is changed. I simplified my problem to this case:
I have a list of object "Widget" which has an attribute name 'type'. I want depending on the type attribute of this list to render html depending on the attribute. To be more specific the Widget.type can have 3 values for example: widget1,widget2 . So in my case I want the directive to return the file widget*.html. (widget1.html for widget type "widget1" etc). Though I pass the argument to the directive using attributes, the value is not evaluated and the string widget.type is return.
Can you help me?
Thx in advance.
app.js file:
var app = angular.module("MainCtrl", []);
app.controller("myCtrl", function($scope) {
function Widget(type){
this.type=type;
}
$scope.widgets=[];
$scope.widgets.push(new Widget('widget1'),new Widget('widget2'),new Widget('widget3'));
});
app.directive('widget', function() {
return {
restrict: 'E',
scope: {
obj: '='
},
templateUrl: function(element,attr){
//console.log(attr);
console.log(attr.obj);
return attr.obj+'.html';
}
}
});
index.html file:
<!DOCTYPE html>
<html ng-app="MainCtrl">
<head>
<meta charset="utf-8" />
<title>AngularJS Plunker</title>
<!-- css -->
<link rel="stylesheet" href="style.css" />
<!-- utilities -->
<script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.4.8/angular.js"></script>
<!-- angular module file -->
<script src="script.js"></script>
</head>
<body ng-controller="myCtrl">
<div ng-repeat="widget in widgets">
{{widget.type}}
<widget obj='widget.type' ></widget>
</div>
</body>
widget1.html file:
<div class="widget">
widget1:{{widget.type}}
</div>
widget2.html,widget3.html are the same
Notice the console output in the directive.
I created a plunker so it's easier to notice the problem:http://plnkr.co/edit/ulBSQQrqpSV9g3BNGRhO?p=preview
First example with your directive: http://plnkr.co/edit/XAXy5RGLnvUZIoRj5xAs?p=preview
Secone example without your directive:
<div ng-repeat="widget in widgets">
<!--{{widget.type}}-->
<div ng-include="widget.template"></div>
</div>
Note: additional property in your Widget-object. Easier to handle.
First one is not as beautiful as the example without the directive, becaue your scope-variable of the directive has to be the same as the variable in your templates ('widget'). I like the second example much more.

Angular validation form

I have a simple form.
<html lang="en" ng-app="MyApp">
<head>
</head>
<body ng-controller="AppCtrl">
<form name="myForm" id="myForm">
<input type="text" ng-model="field" name="myField" />
<div ng-show="myForm.myField.$error" style="color: red">
{{myForm.myField.$error}}
</div>
</form>
<script src="bower_components/angular/angular.js"></script>
<script src="controller.js"></script>
</body>
</html>
And i have angular controller
angular.module('MyApp',[])
.controller('AppCtrl', function($scope) {
$scope.myForm.myField.$error = "just to see it work";
});
Why do I get error '$scope.myForm is undefined'?
You have model, module and controller a little confused. My solutions uses Angular 1.2, although you will soon need to move to Angular 2.
Here is my reworking of your example:
<html lang="en" ng-app="MyApp">
<head>
</head>
<body ng-controller="AppCtrl as ctrl">
<form name="myForm" id="myForm">
<input type="text" ng-model="ctrl.myField" name="myField" />
<div style="color: red">
{{ctrl.myField}}
</div>
</form>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.19/angular.min.js">
</script>
<script src="controller.js"></script>
</body>
</html>
And in the controller.js:
angular.module('MyApp',[])
.controller('AppCtrl', [function() {
this.myField = "just to see it work";
}]);
In the above, I have put "myField" in the scope of the controller "AppCtrl". I have put the whole page under the control of the module 'MyApp'. You can either inject the model with "ng-bind" or use the curly bracket notation in the body of the div to bind to the "myField" model of "ctrl". I have used the latter but be aware this binding will be established after the page has been parsed.
If you load this all now, you should see "just see it work" in red under the text field, and also inside the text field. When you edit the text box, the red text will change in sync. Once you have that working, you will never want to stop learning more about Angular!
I should add that this model has a single attribute. To generalise this you will need to create a model with several properties (one for each input element), so that a JSON object is returned when the form is submitted.
You can't have dots in your variable name.
Try myFormMyFieldError instead of myForm.myField.$error.
Additional: Rather than using the attribute style, use a CSS file.

Change AngularJS urls with ng-model

Is there any way to change AngularJS urls with ng-model?
var scotchApp = angular.module('scotchApp', ['ngRoute']);
scotchApp.controller('mainController', function($scope) {
$scope.gettext = function (){
};
});
<!-- index.html -->
<!DOCTYPE html>
<html ng-app="scotchApp">
<head>
<meta charset="utf-8">
<link rel="stylesheet" href="https://netdna.bootstrapcdn.com/bootstrap/3.0.0/css/bootstrap.min.css" />
<link rel="stylesheet" href="https://netdna.bootstrapcdn.com/font-awesome/4.0.0/css/font-awesome.css" />
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.25/angular.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.25/angular-route.js"></script>
<script src="eventChange.js"></script>
</head>
<body ng-controller="mainController">
<div class="container">
<div class="row">
<div class="col-sm-1">Search</div>
<div class="col-sm-3"><input type="text" class="form-control" ng-model="search" ng-change="gettext()"></div>
</div>
</div>
</body>
</html>
I need to change the URL into something like this http://localhost/angulRoute/search=myVal when user type 'myVal' in the search box (actually inside gettext() function with search value)
You can do something like this in your controller:
$scope.query = $location.search().q;
$scope.$watch('query', function(newValue) {
$location.search('q', newValue);
});
You'd need to inject $location into your controller, and make sure in your route config includes:
reloadOnSearch: true
That would result in a URL like http://localhost/myRoute?q=myVal
Note: I would also add ng-model-options="{updateOn:'blur'}" to your input, to prevent updating the URL on every key press.
EXAMPLE
Here is a working example of how to do this: http://plnkr.co/edit/tphqPeJ0dO74Ux7WpXlU?p=preview
Note that, because of the way plnkr.co works, you won't see the URL changes in the address bar on that site. If you download the code and run it locally, the URL would be updated in the address bar.
Hi I found a javascript solution for that.
$scope.gettext = function (search){
window.history.pushState("object or string", "Title", "/angulRoute/search="+search);
};
with <input type="text" class="form-control" ng-model="search" ng-change="gettext(search)" > worked for me. However anyone have an AngulerJs solution they are welcome :D

AngularJS forms for object with subobjects

How come subobjects do not get the two-way binding:
<!DOCTYPE html>
<html ng-app="app">
<head>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.1/angular.min.js"></script>
<script>
angular.module('app', []).controller('testCtrl', function($scope) {
$scope.doc = { "foo": "bar", "baz": { "zab": "rab" }}
})
</script>
</head>
<body>
<form ng-controller="testCtrl">
<label><span>Foo</span><input ng-model="doc.foo"></label>
<fieldset>
<legend>Baz</legend>
<label ng-repeat="(key,val) in doc.baz">
<span>{{key}}</span><input ng-model="val">
</label>
</fieldset>
<pre><code>{{doc | json}}</code></pre>
</form>
</body>
</html>
If I edit the foo, I can see it update. But if I edit the zab, I cannot see any changes.
Is there some way to make this work, and if not, another data construct (like baz being an array of objects) which could be made to work?
Change ng-model to this:
<span>{{key}}</span><input ng-model="doc.baz[key]">
The reason that val isn't updating your outer scope (testCtrl's scope) is that ng-repeat creates a new scope for each iteration - so you are only binding the input box to the local (iteration's) scope copy of val, not the parent's scope part of your larger object.

Why doesn't AngularJS update the views for model containers?

In the following Angular application, why don't {{myForm}} and {{myForm.userTypeInput}} update when the userTypeInput model is changed.
<!doctype html>
<html ng-app>
<head>
<script src="http://code.angularjs.org/1.0.6/angular.min.js"></script>
<script>
function Ctrl($scope) {
$scope.userType = 'guest';
}
</script>
</head>
<body>
<form name="myForm" ng-controller="Ctrl">
userType: <input name="userTypeInput" ng-model="userType">
<tt>userType = {{userType}}</tt><br>
<tt>myForm = {{myForm}}</tt><br>
<tt>myForm.userTypeInput = {{myForm.userTypeInput}}</tt><br>
</form>
</body>
</html>
The first line updates according to the changes made in the model, but the last couple of lines always remain the same:
myForm = {"userTypeInput":{}}
myForm.userTypeInput = {}
while I expected them to change according to the value I type in userTypeInput.
The name attribute of the element does nothing in terms of how angular treats a DOM element, the ng-model, ng-app, and ng-controller are the only parts in your HTML (along with the data bindings) that Angular will recognize. Since angular doesn't look at the name attribute when resolving variables for binding it doesn't update the other two, Angular is only looking at variables on the scope.

Resources