Angular JS truncate text and add read more - angularjs

I have an ng-repeat that is outputting a number of <p>. I would like to truncate the text and add a read more button that expands when you click it.
This is what I have so far:
//NG-repeat
<div class="col-xs-4 mbm" ng-repeat="wine in wines">
<p readMore> {{wine.copy|truncate: textLength }}
<a ng-click="changeLength()" class="color3"><strong>More</strong></a>
</p>
</div>
//NG-click
$scope.changeLength = function() {
$scope.textLength = 9999;
}
I have a custom directive that is able to truncate the length of the string. But when trying trying to modify the text length via and ng-click I am finding all the of items in the ng-repeat are modified.
Is there a way to change a single ng-repeat item?

Target the wine for the ng-click:
<p readMore> {{wine.copy|truncate: wine.textLength }}
<a ng-click="changeLength(wine)" class="color3"><strong>More</strong></a>
</p>
And then only truncate the targeted text:
$scope.changeLength = function(wine) {
wine.textLength = 9999;
}

Related

AngularJS - How to correctly use ng-show inside a ng-repeat? My boolean isn't getting updated

I have a ng-repeat that loops over 9 divs, each one has a different color.
When the user clicks on one div, its color it's gonna be the background color of a section.
I'm trying to do this:
The array that gets repeated is structured like this:
interface colorBoxes {
color: string;
isSelected: boolean;
}
in the view:
<div ng-repeat="s in vm.colorBoxes track by $index">
<div class="pointer" ng-click="w.backgroundColor = s.color; vm.pickColor(s, $index)" ng-style='{"background-color": s.color}'>
<i ng-show="vm.isColorSelected($index) === true" class="fa fa-check fa-1x checkOnSelectedLegend"></i>
</div>
</div>
in the controller:
pickColor(array: any, index: number) {
for(var i = 0; i<=this.colorBoxes.length; i++) {
this.colorBoxes[i].isSelected = false;
}
array[index].isSelected = true;
}
I use this function so when you click on a DIV, its variable: isSelected gets true, and all the other DIV's have theirs set to false.
I use this variable in the view with a ng-show, to show a check mark on the DIV that is currently selected, but this isn't working, below the function I put in that ng-show
isColorSelected(index:number):boolean {
return this.colorBoxes[index].isSelected
}
What am I doing wrong?
To summarize, I want that when you click on a box, its color string gets applied to another element (that is working correctly with my code), then, that box need to have a check mark appear on top of it, I tried with the above functions, by setting the isSelected var to true when clicked, but it doesnt work.
I'm pretty sure the problem is that angular isn't checking for changes in that ng-show, I just don't know exactly how to make it check for changes, and maybe there is a cleaner way to obtain what I'm trying to do!
Thank you
addded fiddle: http://jsfiddle.net/7zymp2gq/1/
Ok, here you have your code fixed and working:
http://jsfiddle.net/7zymp2gq/4/
Basically there were 2 things wrong with the function $scope.pickColor:
The loop was entering into not existing fields, I have changed the <= with a <
It was updating array[index], and it should be updating $scope.colorBoxes[index]
Instead of using function at ng-show you can use the isSelected property:
<div ng-app="app" ng-controller="Ctrl">
<div class="class1" ng-repeat="s in colorBoxes track by $index">
<div class="pointer class2" ng-click="pickColor(colorBoxes,$index);" ng-init="lastselected=s.isSelected?$index:null" ng-style='{"background-color": s.color}'>
<i ng-if="s.isSelected" class="fa fa-check fa-1x checkOnSelectedLegend"></i>
</div>
</div>
<div class="changeColor" ng-style='{"background-color": chosenColor}'></div>
</div>
Check this demo.

How to bind array with ng-bind-html directive in angularJS?

I want to show for every item different description.
This is the controller:
todoApp.controller('todos',function($scope,todoFactory){
todoFactory.getTodos().success(function (data) {
courses = x2js.xml_str2json(data);
$scope.todos = courses.rss.channel.item;
for(var i = 0 ; i < $scope.todos.length ; i++){
item = $scope.todos[i];
console.log(item.description);
$scope.message = item.description;
}
});
this is the html:
<div ng-controller="todos" class="list" style="padding-top: 8%">
<div class="list card" ng-repeat="todo in todos | filter:search" >
<div class="item item-avatar" ng-click="openLink(todo.link)" >
<img src="Bla-Bla-Logo-1.png">
<h2>{{todo.title}}</h2>
<p>{{todo.pubDate | limitTo:25 }}</p>
</div>
<div class="item item-body">
<p ng-bind-html="message"></p>
<p>
1 Like
5 Comments
</p>
</div>
</div>
<!--end list card-->
</div>
<!--end todos-->
Just to explain the code I get xml and convert into json so todos is array of objects.
Message is entering every object and get the description (but in the description has tags so i use ng-bind-html directive to show it properly).
I understand that $scope.message will hold just the last description. How to make it to belong in the ng-repeat so I can get different description for different item?
Thanks.
replace
<p ng-bind-html="message"></p>
with
<p ng-bind-html="todo.description"></p>
please provide the data which is you want to displayed repeatedly.
How data is represented.You are getting last one because it is overriding.
The "ngBind" attribute tells Angular to replace the text content of the specified HTML element with the value of a given expression, and to update the text content when the value of that expression changes.
Typically, you don't use "ngBind" directly, but instead you use the double curly markup like {{ expression }} which is similar but less verbose.

angularjs how set right scope for function?

have this ng-repeat
<li class="tmmenu-admin-tabs-builder-panel-portlet" ng-repeat="question in questions">
<div>
<span class="tmmenu-admin-tabs-builder-panel-portlet-toggler" ng-click="tatbppTogler()">{{{tatbppt}}}</span>
<span class="tmmenu-admin-tabs-builder-panel-portlet-number">{{question.id}}</span>
{{question.text}}
</div>
<div class="tmmenu-admin-tabs-builder-panel-portlet-options" ng-show="showTatbppo">
...
</div>
</li>
I want, for click in "tmmenu-admin-tabs-builder-panel-portlet-toggler" change visibility "tmmenu-admin-tabs-builder-panel-portlet-options" and change text in "tmmenu-admin-tabs-builder-panel-portlet-toggler".
And i write this code for get result:
$scope.tatbppTogler = function(){
$scope.showTatbppo = !$scope.showTatbppo;
if($scope.showTatbppo){
$scope.tatbppt = "-";
}else{
$scope.tatbppt = "+";
}
}
It's works, but changed dom in all "Li", how changed only current (where user click) "li"?
You can do it like this:
<li class=portlet" ng-repeat="question in questions">
<div>
<span class="toggler" ng-click="showTatbppo=!showTatbppo">{{showTatbppo ? "+" : "-" }}</span>
<span class="number">{{question.id}}</span>
{{question.text}}
</div>
<div class="options" ng-show="showTatbppo">
...
</div>
</li>
Working fiddle, with this concept:
http://jsfiddle.net/x1nguaxj/
btw. You have very-very-very long css class names :)
1 way
you can pass this in ng-click="tatbppTogler(this)" and then in function manipulate with this
2 way
you can create custom directive and apply it to your li element and then on this directive bind click to element and listen , and on click function will be triggered your listener and you will have access on this element
You can create an attribute id for each question and then change based on the id of the question you clicked
I would suggest you'd take a look at $index. From the angularjs docs:
iterator offset of the repeated element (0..length-1)
Using this, you can clearly determine the certain div that was clicked on.

ng-repeater issue Duplicates in a repeater is not allowed

I'm trying to create a form like below, this using ng-repeat directive in angular and it whenever I created a new row complains
"Duplicates in a repeater are not allowed.".
While I understand the solution for this is by putting "track by $index", however it causes another issue, which clicking delete on one row deletes the value of other field. So I suspect that track by index is OK for static text but not input form. So how to use ng-repeat correctly for my case? See my JSFiddle for demo.
My current code :
HTML
<div class="row-fluid spacer10">
<a ng-click="addAKA()" class="btn btn-primary spacer5 left30"><i class="icon-plus icon-white"></i> Add New Alias</a>
</div>
<div class="row-fluid spacer10"></div>
<div class="row-fluid spacer5" ng-repeat="item in aliasList track by $index">
<input type="text" class="span6 left30" ng-model="item">
<button class="btn btn-danger" ng-click="deleteAKA($index)">delete</button>
<BR/>
</div>
Javascript
$scope.addAKA = function ()
{
if($scope.aliasList == null)
{
$scope.aliasList = [];
}
$scope.aliasList.push("");
$scope.aliasjson = JSON.stringify($scope.aliasList);
}
$scope.deleteAKA = function (idx)
{
var aka_to_delete = $scope.aliasList[idx];
$scope.aliasList.splice(idx, 1);
$scope.aliasjson = JSON.stringify($scope.aliasList);
}
Just change the way you iterate. Instead of this:
<div ng-repeat="item in aliasList track by $index">
do this:
<div ng-repeat="item in aliasList">
$index will be still available inside the element, use like this:
<button ng-click='deleteItem($index)'>Delete</button>
See this JSFiddle for a correct solution
There are multiple problems with your approach.
Since you are directly binding a string to ng-model and ng-repeat creates a child scope, any change to the value would not reflect back. Change you scope model to something like
$scope.list = [{text:"one"},{text:"two"}];
and bind to i.text instead of binding to i as you did earlier.
The deleteItem method was called using item instead of index. See my fiddle here
http://jsfiddle.net/JS6aJ/1/

[Angular JS]- Tabs Pane Example - Dynamic Add Tab

I have used the example from Angular JS Homepage and modified it to meet the requirements.
I have added the tabs info in a scope array and manipulate the data based in some conditions.
Issues:
I have attached an ng-bind on tabItem.title, so any change in the text box will update the title, but i want to limit the displaying of the title by 10 chars
When i create a new tab, i want that tab to be the selected one.
How can i select a tab based on some action taken (like on a click move from tab 1 to tab 2)
Fiddle: http://jsfiddle.net/austinnoronha/NWwcT
<br/><br/>
<div ng-cloak ng-app="TabsApp">
<div class="container" ng-controller="TabManagerCtrl">
<span class="label label-info label-ext" ng-click="tabManager.addTab()" style="cursor:pointer">Add a Tab</span><br/><br/>
<div>
<div tabs>
<div ng-repeat="tabInfo in tabManager.tabItems" pane title="{{ tabInfo.title }}">
<p>{{ tabInfo.content }}</p>
<input type="text" ng-model="tabInfo.title" ng-change="tabManager.getTitle(tabInfo)">
</div>
</div>
</div>
<br/><br/><br/>
</div><!-- /container -->
</div> <!-- /container -->
</div> <!-- /app -->
that's strange...
The limitTo filter doesn't seem to work, but you can create a new one and change your line
<div ng-repeat="tabInfo in tabManager.tabItems" pane title="{{ tabInfo.title }}">
by
<div ng-repeat="tabInfo in tabManager.tabItems" pane title="{{ tabInfo.title | limit:10}}">
with
angularApp.filter('limit', function() {
return function (input, value) {
return input.substr(0,value);
};
});
For the select one, I think it doesn't work because you have to have access to the pane scope. One way to do it is to access to access the property from the pane when you create it. In the pane directive, just add :
if(scope.$parent.tabInfo.selected) tabsCtrl.select(scope);
just after the tabsCtrl.addPane(scope); line. But then you also have to change the tabs directive so that the line
$scope.select = function(pane) {
become
this.select = $scope.select = function(pane) {
For your 3rd question, I don't know how to do it in that scheme.
I would make the pane directive different, putting the select function out of the directive, and binding it directly to your tabManager object.
Like this : http://jsfiddle.net/NWwcT/2/
In this cas, you have the 3 requirements, and you can select the tab from ouside by calling tabManager.select(index)

Resources