AngularJS 1 - ng-repeat not re-rendering after array push - javascript

I'm trying to make a simpliest chat app in Angular 1.
Controller code:
app.controller('mainCtrl', function ($scope, $rootScope, $routeParams, $location, $http) {
$scope.messages=[{'name':'user','text':'test'}];
$scope.submitMessage = function () {
$scope.messages.push({'name':'newuser','text':$scope.mymessage});
}
});
Template:
<div class="page-content" ng-controller="mainCtrl" ng-init="init()">
<div class="messages">
<p class="chat-message" ng-repeat="message in messages"><span class="username">{{message.name}}: </span>{{message.text}}</p>
</div>
<div style="clear:both"></div>
<form ng-submit="submitMessage()" ng-controller="mainCtrl">
<input type="text" ng-model="mymessage" class="message-input" ></input>
</form>
When trying to console.log the $scope.messages array, it shows the new values, but the list itself does not change at all. What can be the reason?

You've got ng-controller="mainCtrl" defined twice, this will actually instantiate 2 different instances of the controller, so the messages you push will be on the array in the second instance of your controller while you're repeating over the messages that are on the first instance of your controller.
You only need it on the surrounding div, everything that is nested inside this tag will be able to access the $scope on your controller.
<div class="page-content" ng-controller="mainCtrl" ng-init="init()">
<div class="messages">
<p class="chat-message" ng-repeat="message in messages"><span class="username">{{message.name}}: </span>{{message.text}}</p>
</div>
<div style="clear:both"></div>
<form ng-submit="submitMessage()">
<input type="text" ng-model="mymessage" class="message-input"/>
</form>
</div>

Related

Convert String to html in label AngularJS

I have an angular snippet in which I want to convert string to HTML object.
`<div class="row">
<label class="col-md-4 info_text">Remarks<span>:</span></label> <label
class="col-md-8 fieldValue">{{initialTableInfo.comments}}
</label>
</div>`
The initialTableInfo.comments has the value <b>someText</b>. It is getting printed as it is. I want "someText" to be printed as someText instead of <b>someText</b>.
You can use the $sce parameter for angular.
module.controller('myctrl', ['$scope', '$http', '$sce',function($scope, $http, $sce) {
$scope.initialTableInfo.comments = $sce.trustAsHtml("<b>Some Text<b>");
}]);
And in your HTML use ng-bind-html
<label class="col-md-8 fieldValue" ng-bind-html="initialTableInfo.comment"> </label>
You can render string to html using $sce.trustAsHtml(html) and use ng-bind-html.
DEMO
angular.module("app",[])
.controller("ctrl",function($scope){
$scope.initialTableInfo ={};
$scope.initialTableInfo.comments = '<b>someText</b>';
})
.filter('trustHtml',function($sce){
return function(html){
return $sce.trustAsHtml(html)
}
})
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="app" ng-controller="ctrl">
<div class="background-white p20 reasons" >
<h6><b>About {{aboutlongs[0].name}}</b></h6>
<div class="reason-content" ng-bind-html="$scope.initialTableInfo.comments | trustHtml" >
</div>
</div>
</div>
You should check this link https://docs.angularjs.org/api/ng/directive/ngBindHtml.
<div ng-controller="ExampleController">
<p ng-bind-html="myHTML"></p>
</div>
As Alexi mentioned, be sure to have the correct syntax on the controller too.

use angularjs http json result separately in scope

I used Angularjs $http and $scope to get data from sql server and display it successfully in scopes with no problem. But when I tried to display http json result from separated function in the same scope nothing happened.
All I wanted to know. If I want to get json object in a parameter and select slice from it before displaying, should I make http request every time to do so or can I separate scope away from http request in independent function as shown below.
<%--Angular--%>
<script src="../Scripts/angular.min.js"></script>
<script>
var jsonObj;
var app = angular.module('myApp', []);
app.controller('myCtrl', function ($scope, $http) {
$http.get('../C_Angular.asmx/ShowSlider')
.then(function (response) {
jsonObj = response.data; // this part work well and retrieve data as expected by tracing C_Angular.asmx code
});
Select_From_Json = function (x, y) {
$scope.Categories = jsonObj.slice(x, y); // but this part don't work when I press Button1 to call Select_From_Json
};
});
</script>
When I press Button1 to call Select_From_Json fuction no displaying take place.
<input id="Button1" type="button" value="button" onclick="Select_From_Json(2, 4)" />
<div data-ng-app="myApp" data-ng-controller="myCtrl">
<div data-ng-repeat="Cat in Categories">
<div style="background-image: url('{{Cat.Cat_Pic}}');">
<span>{{Cat.Cat_Name}}</span>
</div>
</div>
</div>
Your button is outside the controllers scope. That is why the Select_From_Json is not executing properly.
Move the button inside the div where the controller is defined.
<div data-ng-app="myApp" data-ng-controller="myCtrl">
<input id="Button1" type="button" value="button" onclick="Select_From_Json(2, 4)" />
<div data-ng-repeat="Cat in Categories">
<div style="background-image: url('{{Cat.Cat_Pic}}');">
<span>{{Cat.Cat_Name}}</span>
</div>
</div>
</div>
You also should be using ng-click for executing functions from a controller like so:
<div data-ng-app="myApp" data-ng-controller="myCtrl">
<input id="Button1" type="button" value="button" ng-click="select_From_Json(2, 4)" />
<div data-ng-repeat="Cat in Categories">
<div style="background-image: url('{{Cat.Cat_Pic}}');">
<span>{{Cat.Cat_Name}}</span>
</div>
</div>
</div>
And in the controller itself:
$scope.select_From_Json = function(x, y){
$scope.Categories = jsonObj.slice(x, y);
}

I am trying to call text from input using angular js

I am trying to call text that has been added to an input using Angular JS, however in my console log I keep getting undefined.
<div ng-controller="favouritesController" class="col-xs-12 favList">
<input type="text" ng-model="newFav" ng-keyup= "add($event)" class="col-xs-12 FavInput" placeholder="Add A Favourite">
<ul>
<li ng-repeat="weatherList in weatherLists" class="col-xs-12">
<span class="col-xs-12 col-sm-8">{{weatherList._id + ' / ' + weatherList.place}}</span>
<div class="col-xs-12 col-sm-2">
<button type="button" name="button" class="deleFav" ng-click="delete(weatherList)">Delete</button>
<div class="col-xs-12">
<input type="text" ng-model="serverip"/>
<button ng-click="save(serverip)">Save</button>
</div>
</div>
</li>
</ul>
</div>
js code
myApp.controller('favouritesController', function($scope, $http, $rootScope, $route, $location) {
$scope.save = function(){
console.log($scope.serverip)
}
})
You don't need to pass the parameter to the save function (and your definition of save doesn't include it).
Change the button to:
<button ng-click="save()">Save</button>
Or either accept the parameter in the function declaration:
$scope.save = function(serverip){
console.log(serverip)
}
ng-repeat creates a new scope, inheriting from the scope above it. You are assigning serverip to this newly created scope. Thus, $scope in the favouritesController's context has no record of this. You should accept a parameter in your save function and log that (as you are passing this function the argument, anyways.)
Edit:
or, as an alternative... Expose a property that will be inherited by ng-repeat:
Controller:
myApp.controller('favouritesController', function($scope, $http, $rootScope, $route, $location) {
$scope.ip = { serverip:'' };
$scope.save = function(){
console.log($scope.ip.serverip)
}
});
Template
<div ng-controller="favouritesController" class="col-xs-12 favList">
<input type="text" ng-model="newFav" ng-keyup= "add($event)" class="col-xs-12 FavInput" placeholder="Add A Favourite">
<ul>
<li ng-repeat="weatherList in weatherLists" class="col-xs-12">
<span class="col-xs-12 col-sm-8">{{weatherList._id + ' / ' + weatherList.place}}</span>
<div class="col-xs-12 col-sm-2">
<button type="button" name="button" class="deleFav" ng-click="delete(weatherList)">Delete</button>
<div class="col-xs-12">
<input type="text" ng-model="ip.serverip"/>
<button ng-click="save()">Save</button>
</div>
</div>
</li>
</ul>
</div>

AngularJS Dynamic Template with indexed scope variable arrays

I'm using AngularJS and trying to create a form where I can dynamically add new inputs, similar to this fiddle: http://jsfiddle.net/V4BqE/ (Main HTML below, working code in fiddle).
<div ng-app="myApp" ng-controller="MyCtrl">
<div add-input>
<button>add input</button>
</div>
</div>
I would like to be able to use a HTML template for my form since the input I'm adding is ~300 lines long. My issue is I cannot figure out how to index the scope variable containing the data when used in a template. I've tried to make my own modified version of the above code on plnkr http://plnkr.co/edit/4zeaFoDeX0sGTuBMCQP2?p=info . However, when I click the button no form elements appear.
Online (plnkr) I get a 404 not found for my template.html, but I think that is just a plnkr limitation. On my machine with a Python HttpServer I get an Error: [$parse:syntax] for the $templateRequest and a TypeError: Failed to execute 'appendChild' on 'Node': parameter 1 is not of type 'Node'. when using the $http.get method.
Any advice for getting the indexed scope variable array to work with an external html file?
Thanks, JR
Edit: Update plnkr link
You can do it without directive & external template
what you are trying to do does not require a directive (it actually much simple with the basic angularjs tools)
http://plnkr.co/edit/LVzGN8D2WSL2nR1W7vJB?p=preview
html
<body>
<div class="container" ng-app="myApp" ng-controller="MyCtrl">
<button class="btn btn-primary" type="button" ng-click="addPhoneInput()">add input</button>
<form>
<div ng-repeat="item in telephoneNumbers">
<hr>
<input type="text" ng-model="item.phone">
</div>
</form>
<hr>
<div class="well">
<h4>Phone Numbers,</h4>
<p ng-repeat="item in telephoneNumbers">{{item.phone}}</p>
</div>
</div>
</body>
js
var app = angular.module('myApp', []);
app.controller('MyCtrl', ['$scope', function($scope) {
// Define $scope.telephone as an array
$scope.telephoneNumbers = [];
$scope.addPhoneInput = function() {
$scope.telephoneNumbers.push({});
};
// This is just so you can see the array values changing and working! Check your console as you're typing in the inputs :)
$scope.$watch('telephoneNumbers', function(value) {
console.log(value);
}, true);
}]);
If you insist using a directive,
http://plnkr.co/edit/BGLqqTez2k9lUO0HZ5g1?p=preview
phone-number.template.html
<div>
<hr>
<input type="text" ng-model="ngModel" >
</div>
html
<body>
<div class="container" ng-app="myApp" ng-controller="MyCtrl">
<button class="btn btn-primary" type="button" ng-click="addPhoneInput()">add input</button>
<form>
<phone-number ng-repeat="item in telephoneNumbers" ng-model="item.phone"></phone-number>
</form>
<hr>
<div class="well">
<h4>Phone Numbers,</h4>
<p ng-repeat="item in telephoneNumbers">{{item.phone}}</p>
</div>
</div>
</body>
js
var app = angular.module('myApp', []);
app.controller('MyCtrl', ['$scope', function($scope) {
// Define $scope.telephone as an array
$scope.telephoneNumbers = [];
$scope.addPhoneInput = function() {
$scope.telephoneNumbers.push({});
};
// This is just so you can see the array values changing and working! Check your console as you're typing in the inputs :)
$scope.$watch('telephoneNumbers', function(value) {
console.log(value);
}, true);
}]);
app.directive('phoneNumber', function(){
return {
replace:true,
scope: {
ngModel: '=',
},
templateUrl: "phone-number.template.html"
}
});

Paginating an AngularJS blog

I'm trying to paginate my blogroll using AngularJS and the MEAN Stack. I have my Articles (blog posts) controller set up, and I've list.html to display everything. I can either get all the blogs to display, or I can get the pagination to increment, but I can't get the blogroll to show 5 items at a time and increment with the pagination.
angular.module('mean.articles')
.controller('ArticlesController', ['$scope', '$routeParams', '$location', 'Global', 'Articles', function ($scope, $routeParams, $location, Global, Articles) {
$scope.global = Global;
$scope.currentPage = 0;
$scope.pageSize = 5;
//I've my create, update and delete methods here.
$scope.find = function() {
Articles.query(function(articles) {
$scope.articles = articles;
});
};
$scope.numPages = function() {
return Math.ceil($scope.Articles.length / $scope.pageSize);
};
And here's my list.html:
<div class="container" style="width:900px; margin:auto">
<div class="container" style="width:600px; float:left">
<section data-ng-controller="ArticlesController" data-ng-init="find()">
<ul class="articles unstyled" style="width:600px">
<li data-ng-repeat="article in articles | filter:search | limitTo:pageSize">
<h2><a data-ng-href="#!/articles/{{article._id}}">{{article.title}}</a></h2>
<div>{{article.content}}</div>
<div>{{article.tags}}</div>
<h4><small>
<div class="well well-small text-center" style="width:300px">
<div style="margin:auto">
<span>{{article.created | date:'medium'}}</span> /
<span>{{article.user.name}}</span>
</div>
</div>
</small></h6>
</li>
</ul>
<h1 data-ng-hide="!articles || articles.length">No articles yet. <br> Why don't you Create One?</h1>
<button ng-disabled="currentPage == 0" ng-click="currentPage=currentPage-1">
Previous
</button>
{{currentPage+1}}/{{numPages()}}
<button ng-disabled="currentPage >= numPages()-1" ng-click="currentPage=currentPage+1">
Next
</button>
</section>
</div>
<div class="container" style="width:300px; float:left">
<input type="text" ng-model="search" placeholder="Enter your search terms" />
</div>
http://jsfiddle.net/2ZzZB/56/ from Pagination on a list using ng-repeat. It looks like the main thing you're missing is a way to indicate where to start your ng-repeat. The fiddle I linked to solves it by creating a startFrom filter.

Categories

Resources