This is my HTML structure in Ionic project.
<div ng-model="pollPage.test.username">updated content</div>
{{pollPage.test.username}}
Controller:
vm.test = {
username : 'static',
}
When I use check my page, its getting 'static' text however it should be 'updated content'
Whats the problem? I guess everything is right but its not working.
Thanks.
Your code is wrong it shoulbe like this:
<div ng-controller="yourController as vm">
<input type="text" ng-model="vm.pollPage.test.username">
<div>{{pollPage.test.username}}</div>
</div>
You cant asign ng-model to a div it must be on elements I/0 like inputs, dropdowns, checks, etc.
Controller:
var vm = this;
vm.pollPage = {};
vm.pollPate.test = {
username : 'static',
}
ng-model should be on an element that its content changes like: input, select, textarea...etc
Related
I have a constant file which looks like this
demo.constant.js
// Add detail constans here
(function () {
angular.module('myApp').constant('TYPE', {
DYNAMIC: 'dynamic',
STATIC: 'static'
});
}());
Now I have a controller file that looks similar to this.
demo.controller.js
(function() {
var DemoController = function(DEP1,DEP2, .... , TYPE)
console.log(TYPE.DYNAMIC); // works perfectly
var self = this;
self.type = '';
...
...
angular.module('myApp.controllers').controller('DemoController', DemoController);
})();
I am trying to access these constants in the HTML file like this:-
<div ng-controller="DemoController as self">
<span ng-if="(self.type === 'dynamic')"> <!--instead of 'dynamic' I want to use TYPE.DYNAMIC-->
...
...
...
</span>
</div>
Note:- {{self.type}} works but {{TYPE.DYNAMIC}} doesn't.
Another problem is that I want to use this constant as the value of radio buttons.
somewhat like this:-
<input type="radio" name="type" ng-model="self.inputType" value="dynamic"> <!-- Here I want to use TYPE.DYNAMIC -->
<input type="radio" name="type" ng-model="self.inputType" value="static"> <!-- Same as above -->
I have searched everywhere but nothing seems to work. Please Help!!
One approach is to assign the constant to a controller property:
function DemoController(DEP1,DEP2, /*.... ,*/ TYPE) {
console.log(TYPE.DYNAMIC); // works perfectly
this.TYPE = TYPE;
}
angular.module('myApp.controllers').controller('DemoController', DemoController)
Then use it in the template:
<div ng-controller="DemoController as $ctrl">
<span ng-if="$ctrl.type === $ctrl.TYPE.DYNAMIC">
...
</span>
</div>
Note: The ng-if directive uses creates a child scope. Consider instead using the ng-show directive which uses CSS and less resources.
You can use $rootScope and initilize it in run phase:
angular.module('app')
.run(function ($rootScope, TYPE) {
$rootScope.TYPE = TYPE
});
then you can use it directly in your HTML
I'm trying to display a link <a href> when a condition is met, but the link never appears.
I have already tried to change the position (in/out of <div controller>) and the tag of the item containing the ng-if (span, div, ul...). This kind of code works on another HTML I have, so my Angular version seems okay.
Here is the form where I call the controller:
<div ng-controller="userRole">
<form ng-submit="setProfile()">
<select ng-model="userRole"
ng-options="role for role in roles">Role</select>
<input type="text"
ng-model="userName"
placeholder="Nom"></input>
<input type="submit"
value="Valider"></input>
</form>
</div>
The condition right after:
<span ng-if="user.isSetup">
Accès aux cours
</span>
And the actual controller:
var app = angular.module('srsApp', []);
app.controller('userRole', function($scope) {
$scope.roles = ['Professeur', 'Élève'];
$scope.user = {role:'', name:'', isSetup: false};
$scope.setProfile = function() {
if ($scope.userName !== '' && $scope.userRole !== '') {
$scope.user.role = $scope.userRole;
$scope.user.role = $scope.userName;
$scope.user.isSetup = true;
$scope.userRole = '';
$scope.userName = '';
}
};
});
</script>
I expected the link to appear once I submit the form with a role and a name, but the link stays hidden. No error from my Firefox terminal, and I know it enters the function because the placeholders are re-initialized.
As mentionned by #AnuragSrivastava, the <span> should be in the <div ng-controller="userRole">. As I said I tried it, but previous circumstances (syntax errors NOT highlighted by terminal) prevented this to work.
I have a form field (input text) with an ng-if being false at the begining. At some point the ng-if value become true.
When this happen, I want to execute some javascript which manipulate the DOM. To keep it simple, let's say that I need to select the input value and focus the field.
<input type="text" ng-value="foo" ng-if="show" onshow="doSomething()"/>
<button ng-click="toggle()"></button>
The JavaScript
ctrl.foo = "bar";
ctrl.show = false;
ctrl.toggle = function(){
ctrl.show = !ctrl.show;
}
I know that it looks like a "non-angular approach", but here I think the action is not model related.
Since the ng-if directive execute the template each time show become true, you can use ng-init for that. See the following snippet and replace alert('test); by anything you want.
angular.module('test', []).controller('test', function($scope, $element) {
$scope.show = false;
$scope.toggle = function() {
$scope.show = !$scope.show;
};
$scope.init = function() {
alert($element.find('input').val());
};
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="test">
<div ng-controller="test">
<input type="text" value="foo" ng-if="show" ng-init="init()" />
<button ng-click="toggle()">Toggle</button>
</div>
</div>
EDIT: It seems my issue is more complex than the simple typo in the code below. I have 3rd party components interacting and raising change events on the inputs which angular is picking up when I don't want it to. The problem is somewhere in there. I will try to find a simple fiddle and update the question if I manage it.
I have a pair of inputs, which have an ng-model and share an ng-change function. The ng-change sets a boolean value in the controller which is supposed to update the class(es) on the inputs through an ng-class directive. However the first of the two inputs never seems to get any updates to it's class. Here is a simplified version:
View:
<div ng-controller='TestCtrl'>
<input type="text" ng-class="{ 'invalid': firstInvalid }" ng-model="firstValue" ng-change="doOnChange()"></input>
<input type="text" ng-class="{ 'invalid': secondInvalid }" ng-model="secondValue" ng-change="doOnChange()"></input>
</div>
Controller:
function TestCtrl($scope) {
$scope.firstInvalid = false;
$scope.secondInvalid = false;
$scope.firstValue = '';
$scope.secondValue = '';
$scope.doOnChange = function () {
console.log('change fired');
$scope.firstInValid = !$scope.firstInvalid;
$scope.secondInvalid = !$scope.secondInvalid;
};
};
Codepen:
http://codepen.io/Samih/pen/ZGXQPJ
Notice how typing in either input, the second input updates with the class just as I would expect, however the first never gets the 'invalid' class.
Thanks in advance for your help.
Check your code for typos:
This line
$scope.firstInValid = !$scope.firstInvalid;
should be
$scope.firstInvalid = !$scope.firstInvalid;
It should be $scope.firstInvalid, not $scope.firstInValid.
It seems to work for me :
Just edited 'firstInvalid'.
View:
<div ng-controller='TestCtrl'>
<input type="text" ng-class="{ 'invalid': firstInvalid }" ng-model="firstValue" ng-change="doOnChange()"></input>
<input type="text" ng-class="{ 'invalid': secondInvalid }" ng-model="secondValue" ng-change="doOnChange()"></input>
</div>
Controller:
function TestCtrl($scope) {
$scope.firstInvalid = false;
$scope.secondInvalid = false;
$scope.firstValue = '';
$scope.secondValue = '';
$scope.doOnChange = function () {
console.log('change fired');
$scope.firstInvalid = !$scope.firstInvalid;
$scope.secondInvalid = !$scope.secondInvalid;
};
};
Codepen: http://codepen.io/vikashverma/pen/BNwKmQ
I have a simple angular controller in my app. And I wish to enhance a page containing static content, with angular. This will allow me to have a good, content rich page as fall back for those without JS (who?!) and web crawlers and readers.
So far I have identified a few ways to do this, possibly using custom directives, or by doubling up content in 'ng-bind-template' directive (which is obviously not ideal).
I am fairly new to the world of angular so would like to try and garner the best practice for this scenario.
What is the best approach for this?
Controller:
app.controller('TestArticle',function($scope, feed){
$scope.initValue = "This is angular injecting this"
$scope.activate = function(){
$scope.eTitle = "Dynamic title";
$scope.eContent = "Dynamic content";
};
});
Markup:
(The problem here is that 'Static content' is replaced by '' if angular initializes)
<div ng-controller="TestArticle">
<div ng-cloak ng-bind-template='{{eTitle}}'>Static content</div>
<div ng-cloak ng-bind-template='{{eContent}}'>Some more content</div>
<div ng-cloak>{{initValue}}</div>
<a href ng-click="activate()" ng-cloak>click to activate</a>
</div>
EDIT
I should be clear that even though angular is bootstrapping, The aim is to leave the default content intact, and not replace it with dynamic content. That only wants to be achieved once the activate button is clicked. I have tried the following but it involves doubling up the content which could get bulky if it is a whole article.
<div ng-controller="TestArticle">
<div ng-cloak ng-bind-template='{{eTitle || "Static Content"}}'>Static content</div>
<div ng-cloak ng-bind-template='{{eContent || "Some more content"}}'>Some more content</div>
<div ng-cloak>{{initValue}}</div> <a href ng-click="activate()" ng-cloak>click to activate</a>
</div>
You can create a simple directive to create the html structure that you want.
I propose this to be your new html:
<div ng-cloak sk-custom-bind="eTitle">Static content</div>
Notice how you don't have to specify the or clause with the static content.
Now you can create a directive that will build the html template for you:
app.directive('skCustomBind',function() {
return {
restrict: 'A',
template: function(elem, attrs) {
var templ = "<div ";
templ += "ng-bind-template='{{";
templ += attrs.skCustomBind;
templ += ' || "';
templ += elem.text();
templ += '"';
templ += "}}'></div>";
return templ;
},
replace: true
};
});
And as simple as that you have the functionality that you are looking for without the duplication.
See this plunker to see a working sample.
The thing here is that when you define the controller, angular will parse through the html to find all the variables and link them with the corresponding controller items using $scope.
So, when angular initializes, since eTitle and eContent are not having any values (since you initialize them in the function only), which is called on click of the last item(where on your application works fine).
So until you click the button, the static text is replaced by $scope.eTitle and $scope.eContent both of which are undefined. Hence no text inside the tags.
So the solution,
1. Either you initialize the variables inside the controller with the static text, like you did for 'This is angular injecting this'(reason only this came!):
app.controller('TestArticle',function($scope, feed){
$scope.initValue = "This is angular injecting this";
$scope.eTitle = "Dynamic title";
$scope.eContent = "Dynamic content";
$scope.activate = function(){
$scope.eTitle = "Dynamic title";
$scope.eContent = "Dynamic content";
};
});
Or you can initialize the variables in the html using ng-init, it will initialize the variable in html only:
<div ng-controller="TestArticle">
<div ng-init="eTitle = 'Static Content'" ng-cloak ng-bind-template='{{eTitle}}'>Static content</div>
<div ng-init="eContent = 'Some more content'" ng-cloak ng-bind-template='{{eContent}}'>Some more content</div>
<div ng-cloak>{{initValue}}</div>
<a href ng-click="activate()" ng-cloak>click to activate</a>
</div>
The thing is when you start using angular, the html will get kind of hijacked and angular will start using its own variables.
Thanks to #JoseM for putting me on to right track and helping me find the following solution...
SOLUTION
My Markup:
NOTE: the custom directive and properties ('cg-dyn' and 'cg-content'). These will not initialise any values when angular bootstraps. And further down you will see how these map from controller scope via an isolated scope.
<div ng-controller="TestArticle">
<div ng-cloak cg-dyn cg-content="eTitle">Static content</div>
<div ng-cloak cg-dyn cg-content="eContent">Some more content</div>
<div ng-cloak>{{initValue}}</div>
<a href ng-click="upDateTitle()" ng-cloak>Update title</a> | <a href ng-click="upDateContent()" ng-cloak>Update content</a>
</div>
My Controller:
app.controller('TestArticle',function($scope, feed){
$scope.initValue = "This is angular injecting this"
$scope.upDateTitle = function(){
$scope.eTitle = "Dynamic title";
};
$scope.upDateContent = function(){
$scope.eContent = "Dynamic Content Lorem ipsum";
};
});
And finally the magic in My Directive
app.directive('cgDyn',function() {
return {
restrict: 'A',
scope:{
'content':'=cgContent'
// this is a two way binding to the property defined in 'cg-content
},
link: function(scope, elem, attrs) {
// below is a watcher keyed on a combination content
scope.$watch('content',function(){
if(scope.content){
elem.html(scope.content);
// and here is the bit, normally plumbed by default, but instead we only replace the html if the value has been set
}
});
},
controller: 'TestArticle',
replace: false
};
});
Thanks for everyone's help. I am sure there is an even better solution out there so keep the suggestions coming!