Display a long message in desired format using AngularJS - angularjs

I have long message string. Each parent message is separated by a symbol # and child message separated by a symbol ^.
$scope.messages = "Message1#Message2#Message3#Message4^Message41^Message42#Message5^Message51^Message52^Message53^Message54^Message55";
I want to display these messages in an unordered list format like below.
I used ng-repeat with ul-li to show the messages but the child messages are not properly aligned as nested ul-li elements and also show repeated messages.
<ul>
<li ng-repeat="message in messages.split('#')">
{{message}}
<ul>
<li ng-repeat="msg in message.split('^')">
{{msg}}
</li>
</ul>
</li>
</ul>
But this code doesn't show the desired output. My effort resides here.

Its better to convert the string into an object beforehand. I've tried to convert it into an object form so that it becomes easier for the template to read and conditionally show the parent-children relationship.
angular.module('app', [])
.controller('ctrl', function($scope) {
$scope.messages = "Message1#Message2#Message3#Message4^Message41^Message42#Message5^Message51^Message52^Message53^Message54^Message55";
$scope.messages = $scope.messages
.split("#").reduce((acc, item) => {
if (item.includes('^')) {
let c = item.split('^');
acc[c[0]] = c.slice(1, -1);
} else {
acc[item] = null;
}
return acc;
}, {});
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="app" ng-controller="ctrl">
<ul>
<li ng-repeat="(key, value) in messages">
{{key}}
<ul ng-if="value">
<li ng-repeat="child in value track by $index">
{{child}}
</li>
</ul>
</li>
</ul>
</div>

You almost done it, check out some modifications:
angular.module('app', []).controller('MyCtrl', function($scope) {
$scope.messages = "Message1#Message2#Message3#Message4^Message41^Message42#Message5^Message51^Message52^Message53^Message54^Message55";
})
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js">
</script>
<ul ng-app='app' ng-controller="MyCtrl">
<li ng-repeat="message in messages.split('#')">
{{message.split('^')[0]}}
<ul>
<li ng-repeat="msg in message.split('^').splice(1)">
{{msg}}
</li>
</ul>
</li>
</ul>

I think this is what are you looking for
<li ng-repeat="message in messages">
{{message.text}}
<ul>
<li ng-if="message.sub" ng-repeat="msg in message.sub">
{{msg}}
</li>
</ul>
</li>
$scope.myFilter = function(input){
if(typeof input == 'string'){
var result = [];
var items = input.split('#');
for(var i=0;i<items.length;i++){
var item = items[i];
if(item.indexOf('^') == -1){//item doesn't have '^' means parent message
result.push({text:item});
}else{
//here my logic goes wrong to split child messages
var subItems = item.split('^');
//now If I push this subItems directly into result, not a good idea
result.push({sub: subItems.splice(1, subItems.length), text: subItems[0]});
}
}
return result;
}
return [];
};
https://jsfiddle.net/va94nqvd/12/

Related

how to bind $index from ng-repeat to controller

In Angular I wanted to bind $index to controller. How can I send $index value in to my controller. Here is my html code.
<body>
<div class="container">
<div class="row row-content" ng-controller="demoController as demoCtrl">
<ul>
<li ng-repeat="val in demoCtrl.list" >Hello {{$index}}</li>
</ul>
</div>
</div>
Here is my controller code
var app = angular.module('confusionApp',[])
app.controller('demoController', function(){
var list = [1,2,3,4,5];
this.list = list;
var array = ['abc','def','ghi','jkl','mno']
this.array = array
console.log(this.array[index]);
});
I need to use ng-modal in HTML and bind that value to some variable in my controller.
Based on the selection of index, it should check in array and respective array should have to print.
Can any of you please help
To get your current iteration position in your controller you have define a function.
So your html code like this.
<body>
<div class="container">
<div class="row row-content" ng-controller="demoController as demoCtrl">
<ul>
<li ng-repeat="val in demoCtrl.list" ng-click="dispArray($index)">Hello {{$index}}</li>
</ul>
</div>
</div>
And your controller code
var app = angular.module('confusionApp',[])
app.controller('demoController', function($scope){
$scope.dispArray = function(index){
// console.log(index);
// your code
}
});
Depending on what you're trying to accomplish you might be better served creating a custom iterator.
function makeIterator(array){
var nextIndex = 0;
return {
next: function(){
return nextIndex < array.length ?
{value: array[nextIndex++], done: false} :
{done: true};
}
}
}
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Iterators_and_Generators
Angular is going to iterate over everything in the list when you use ngRepeat. If you're trying to track which list item a user clicks then you'll just add that in there using $index.
<li ng-repeat="val in demoCtrl.list" >
<span ng-click="demoCtrl.userClicked($index)"> Hello {{$index}}</span>
</li>
If you're just trying to print the data in each item, ng-repeat is already iterating everything for you.
<li ng-repeat="val in demoCtrl.list" >
<span ng-click="demoCtrl.userClicked($index)"> Hello {{val}}</span>
</li>
It all depends on what you're trying to do.
i dont konw what u want to do. if u want to use event. you can pass $index to your controller function like:
<li ng-repeat="val in demoCtrl.list" ng-click="getIndex($index)">Hello {{$index}}
$scope.getIndex = function($index) {
console.log($index)
}
hope to help u.

$scope data is not updating in view for the first time

controller.js
$scope.getElectInfo=function(){
var selectedVal = $("#countriesList option:selected").val();
if (selectedVal != 0) {
$.get(APP_URL+ "/political/ElectionType/GetElectionTypesByCountry?countryId="
+ selectedVal,
function(data, status) {
$scope.data1=data;
console.log($scope.data1);
});
$scope.Structure = true;
}else
{
$scope.Structure = false;
}
}
html
<select id="countriesList" ng-change="getElectInfo()" ng-model="getElectionInfo">
</select>
<div ng-show="Structure" class="content">
<figure class="org-chart cf">
<ul class="administration">
<li>
<ul class="director">
<li>
<ul class="subdirector">
</ul>
<ul class="departments cf">
<li><a ><span ng-repeat="cname in country">{{cname.countryName}}</span></a></li>
<li class="department dep-b" ng-repeat="types in data1">
<a ><span>{{types.name}}</span></a>
</li>
In the above controller.js i am getting the country wise election types data,in the html page when i select the country for the first time $scope.data1 is not updating in view,select second time its updating can any one help me what is the problem!
finally i got it,
need to place $scope.$apply(); in function(data, status) { }

Angular.js - ng-repeat not working

Angular.js is pretty new to me. I have learned before the $scope method for the controller and now trying the "this" method. For some reason I can not get my ng-repeat to work. here's my code:
HTML:
<ul class="nav nav-pills">
<li><a ng-click="myCtrl.tab=1" href>one</a></li>
<li><a ng-click="myCtrl.tab=2" href>two</a></li>
<li><a ng-click="myCtrl.tab=3" href>three</a></li>
</ul>
<div ng-controller="imageContr as imageCtrl">
<div ng-show="myCtrl.tab === 1" class="tab">
<h3>ONE title</h3>
<p>hello</p>
<li ng-repeat="item in gallery">
<img alt="imagealt" ng-src="{{item.photo}}">
</li>
</div>
<div ng-show="myCtrl.tab === 2" class="tab">
<h3>TWO title</h3>
<p>how are</p>
</div>
<div ng-show="myCtrl.tab === 3" class="tab">
<h3>THREE title</h3>
<p>you?</p>
</div>
</div>
</section>
</body>
</html>
APP.JS:
(function() {
var app = angular.module('myApp', []);
app.controller('myController', function() {
this.tab = 1;
});
app.controller('imageContr', function() {
this.gallery = images;
var images = {
photo: 'image1.jpg'
};
});
})();
Declare images before you assign it, and make it an array
var images = [{ photo: 'image1.jpg' }];
this.gallery = images;
Then in your view:
<li ng-repeat="item in imageCtrl.gallery">
<img alt="imagealt" ng-src="{{item.photo}}">
</li>
You are storing the gallery on this of the controller (which is basically the $scope), hence you need to access it in the template via imageContr as well:
<li ng-repeat="item in imageCtrl.gallery">
<img alt="imagealt" ng-src="{{item.photo}}">
</li>
You could also consider making gallery an array, so can easily iterate over it. Or you need to use the "iterate over object properties"-syntax:
<div ng-repeat="(key, value) in myObj"> ... </div>

How to Close other accordian in angular js

In the below code I am using toggle function which is working properly, but I want to close other accordingly, when one is open
<div class="listing_cat" ng-controller="categoryCtrl">
<ul>
<li class="mob_main_cat" ng-repeat="x in categories" ng-click="toggleCustom($index, $event)" >
<span class="cat_left"> {{x.category}}</span> <span class="cat_right"><i class="fa fa-plus"></i></span>
<div class="clearfix"></div>
<ul class="mob_sub_cat" ng-show="custom[$index]">
<li class="head">View all in Education</li>
<li ng-repeat="x in subcategories">{{x.subcategory}}</li>
</ul>
</li>
</ul>
</div>
<script>
$scope.custom = [];
$scope.toggleCustom = function(obj,event) {
event.stopPropagation();
$scope.custom[obj] = !$scope.custom[obj];
};
</script>
http://jsfiddle.net/U3pVM/16884/
Above is my jsfiddle link in which i want to close another when any one is clicked
Updated your fiddle with a solution, here:
http://jsfiddle.net/4m92fsqy/
Controller:
$scope.toggleCustom = function (obj, event) {
event.stopPropagation();
var temp = $scope.categories[obj].shown
for (var i=0; i < $scope.categories.length; i++) {
$scope.categories[i].shown = false;
}
$scope.categories[obj].shown = !temp;
};
HTML:
<ul class="mob_sub_cat" ng-show="categories[$index].shown">
Should be simple enough :)

ng-click function using $index as parameter throws Unexpected token error

So I ma trying to loop through an array and create an list item for each object in it.
However when then adding an ng-click to that item i get the following error, even though the code prints out correctly.
Syntax Error: Token '$index' is unexpected, expecting [:]
I have the following code:
<body ng-controller="VideoController as VidCtrl">
<div class="row" id="grid">
<div ng-repeat="array in videos" ng-show="VidCtrl.isActive({{$index}})">
<ul class="small-block-grid-3">
<li ng-repeat="video in array" ng-click="VidCtrl.setVideo({{$index}})">
<img src="{{video.image}}">
<div>
<h5>{{video.title}}</h5>
<p>{{video.ingress}}</p>
</div>
</li>
</ul>
</div>
<ul class="pagination">
<li ng-class="{'current':isActive($index)}" ng-repeat="array in videos"><a ng-click="VidCtrl.setPanel($index)" href="#">{{$index + 1}}</a></li>
</ul>
</div>
And This is my js:
var videos = [];
var activeVideo = null;
var app = angular.module('webb-tvApp', []);
app.controller('VideoController', function($scope){
$scope.videos = videos;
this.activePanel = 0;
this.setPanel = function(val){
this.activePanel = val;
}
this.isActive = function(val){
return this.activePanel === val;
}
this.setVideo = function(vidIndex){
console.log(videos[this.activePanel][vidIndex]);
}
});
The videos array has the following structure.
var videos = [
[
{
image: "foo",
title: "bar",
ingress: "foobar",
},
{},
{}
],
[
{},
{},
]
]
I am new to angular so go easy on me.
When using these directives you can use the variables without interpolation {{}}. Additionally, you can use ng-src with your images instead of using src.
<body ng-controller="VideoController as VidCtrl">
<div class="row" id="grid">
<div ng-repeat="array in videos" ng-show="VidCtrl.isActive($index)">
<ul class="small-block-grid-3">
<li ng-repeat="video in array" ng-click="VidCtrl.setVideo($index)">
<img ng-src="{{video.image}}">
<div>
<h5>{{video.title}}</h5>
<p>{{video.ingress}}</p>
</div>
</li>
</ul>
</div>
<ul class="pagination">
<li ng-class="{'current':isActive($index)}" ng-repeat="array in videos"><a ng-click="VidCtrl.setPanel($index)" href="#">{{$index + 1}}</a></li>
</ul>
</div>
Few things I noticed:
Remove interpolation from inside ng-show and ng-click
<div ... ng-show="VidCtrl.isActive($index)">
...
<li ... ng-click="VidCtrl.setVideo($index)">
And replace src with ng-src
<img ng-src="{{video.image}}">

Resources