ng-repeat with an if-statement in Angular - javascript

I have a website with a huge list of 30 articles. Until now this was like 300 lines of HTML code and with angularjs it is now like 10 lines. But some of these articles are special and so I need to be more specific what to show. Here is the HTML code:
<div id="illustratorcontent" ng-repeat="illustrator in illustrators">
<article id="illustratorcontent{{illustrator.ID}}">
<header>
<h3>{{illustrator.name}}</h3>
</header>
<div class="illustratorcontentext">
<p>This work is copyrighted and owned by {{illustrator.name}}...</p>
<p>Details of the copyright holder: </p>
<ul class="listplacing">
<li>Name: {{illustrator.name}}</li>
<li>Website: {{illustrator.name}}'s website</li>
<li>Website: {{illustrator.name}}'s {{illustrator.website2text}}</li>
</ul>
</div>
</article>
</div>
and the IllustratorController is:
function Illustrator ($scope){
$scope.illustrators = [
{
"ID" : "Ilus1",
"name" : "Ilus1",
"website" : "http://Ilus1page.com/"
},{
"ID" : "Ilus2",
"name" : "Ilus2",
"website" : "http://Ilus2page.com/"
}, ...
{
"ID" : "IlusX",
"name" : "IlusX",
"website" : "http://IlusXpage.com/"
"website2text" : "Twitter IlusX",
"website2url" : "http://twitterilusx.com/"
}
]
}
So my question is how can I show the existing information and leave the li out where no info is given.
So on this line:
<li>Website: {{illustrator.name}}'s {{illustrator.website2text}}</li>
how can I say that this line is just shown when the object parameter is given or not empty. I already looked for some ways. There is something called ng-if and ng-ui but that did not work out for me. Also there is a way to realize it with classes and hiding divs. But actually I would prefer to not generate them. And the website2url/website2text is just an example, there are more values than this.
Similar questions, but mine is a bit more special I believe:
angular ng-repeat with condition
https://stackoverflow.com/questions/28334600/paginating-angular-ng-repeat-with-nested-filtering

Hello create filter for to show the link of not like
<li ng-if="showSecondWebLink(illustrator)">....</li>
create function in your controller
$scope.showSecondWebLink = function(illustrator){
if(illustrator.website2url && illustrator.website2text ){
return true;
}
return false;
}

Just try with:
<li ng-if="illustrator.website2url && illustrator.website2text">...</li>

Related

Find linked DOM nodes by path with JsViews

Is there an easy way to find DOM nodes in the property path of the linked JS object?
For exmpale I have some object
<script type="text/javascript">
model = {
companyName : "JS Corporation",
address : "",
staff : [
{
name : "Jack Brown",
position : "SW developer"
},
{
name : "John Dow",
position : "Big Boss"
},
{
name: "Billy Hill",
position : ""
}
]
}
</script>
and template
<!-- TEMPLATE -->
<script type="text/x-jsrender" id='companyTamplate'>
<p>company name <input data-link='companyName'></p>
<p>address <input data-link='address'></p>
<fieldset>
<legend>Staff</legend>
{^{for staff}}
<div class='person'>
<p> name <input data-link='name'> </p>
<p> position <input data-link='position'> </p>
</div>
{{/for}}
</fieldset>
</script>
and link them
$.templates('#companyTamplate').link('#companyView',model);
Then I send my object as JSON to a server and get a validation error like this
{
errors : [
{
"path" : "address",
"error" : "empty string"
},
{
"path" : "staff[2].position",
"error" : "empty string"
}
]
}
I want to highlight the input field for address and postion.
For highlighting the address field i can just navigate to
input[data-link=address]
But when I have an error in some array member it's not so evident.
Workaround is to add in input field an attribute with a full path
<input data-link='position' data-link-path='staff[{{:#index}}].position' >
and then navigate to
input[data-link-path="staff[2].position"]
But it's easy to forget add the additional attribute.
Is there a more simple way to solve this problem?
There is not necessarily a one to one mapping from data node to views or DOM nodes. You could have one to none, or one to many (for example if you had two {^{for staff}} tags in your template).
But if you are able to use knowledge of the template structure, then you can navigate the view hierarchy and use APIs such $.view() view.contents() view.childTags() to get from the data back to a chosen element on which you want to act programmatically.
For example in your sample, the following gets the jQuery object for the "Billy Hill" 'position' input:
$.view().get(true, "array").views[2].contents(true, 'input[data-link="position"]')
If you had two {^{for staff}} blocks and you want to navigate to elements in the second block, you can use childTags() APIs to get to the second one:
$.view().childTags("for")[1].tagCtx.contentView.views[2].contents(true, 'input[data-link="position"]')
which again gets you to the "Billy Hill" 'position input'.
See View Hierarchy, $.view() and the various view object and tag object APIs.

Can I make an attribute appear only once in a vue v-for

I have an array of people with associated teams. I want to display all the people in the record, but I only want to display their team name once.
Meaning, if the v-for loop has encountered this particular team name, it should put it in a new temporary array to signify that it should be unique, then when it encounters that team name again, checks it through that temporary array and prevent it from showing again.
Sample HTML Code:
<div id="a-list">
<div v-for="person in people">{{person.Name}}, {{person.Team}}</div>
</div>
Sample Vue Code:
var crew = new Vue({
el: "#a-list",
data: {
people:
[ { "Name": "Richard","Team":"DMS"}, { "Name": "Mark","Team":"VV"}, { "Name": "Steve","Team":"VV"}, {"Name":"Koji","Team":"MZ"}, {"Name":"Jamie","Team":"VV"} ]
}
});
Expected Output:
Richard, DMS
Mark, VV
Steve,
Koji, MZ
Jaimie,
Is this possible to do directly from the v-for loop and not in the JS file?
Edited to show more data that are not sequential
Update: As Fabio has pointed out, the above scenario wouldn't make much sense unless the order of the team is arranged sequentially in the output first. So his answer is correct.
This could be a solution:
<div id="a-list">
<div v-for="(person,index) in people"> {{person.Name}}, {{ ((index == 0) || person.Team != people[index-1].Team) ? person.Team : '' }}</div>
</div>

Dynamic classes using ng-repeat in AngularJS

This is not a duplicate.
In the other post, they are just doing a ternary operation. I wanna changes classes within ng-repeat.
I have this piece of code with little bugs.
HTML:
<div id="server-id-list-container" class="panel-body col-md-12 scrollbar">
<div class="server-id-list-element" ng-class="serverIdLength > 12 ? 'col-md-3' : 'col-md-2'" ng-repeat="server in selection.serverIds">
<p class="alert alert-info">{{server.serverId}}<span ng-click="removeServerId($index)" class="glyphicon glyphicon-remove"></span></p>
</div>
</div>
Controller:
_.forEach($scope.selection.serverIds, function(a) {
$scope.serverIdLength = a.serverId.length;
});
Scope Object:
[
{
"serverId": "loma1pwipdb2002",
"serverName": "",
},
{
"serverId": "shdmqprtp1",
"serverName": "",
}
]
When I enter "loma1pwipdb2002", the class becomes col-md-3 and since I am using ng-repeat applies for all elements. I want the class to be applied only to serverIdLength > 12 and if its lesser than 12, col-md-2 should get applied.
Please advice.
Is it correct that you want to switch your class for each element of selection.serverIds list separately based on serverId string length? Need to know your selection.serverIds, is it your "Scope Object"? If yes, then I would do just
<div
class="server-id-list-element"
ng-repeat="server in selection.serverIds"
ng-class="server.serverId.length > 12 ? 'col-md-3' : 'col-md-2'"> ... </div>
The problem is that your $scope.serverIdLength is being calculated once for all the list. While you want to have a dynamic class based on each item specific property.
Let's continue discussion if I didn't understand the issue and the entry conditions.
the issue seems to lie here:
_.forEach($scope.selection.serverIds, function(a) {
$scope.serverIdLength = a.serverId.length;
});
No matter what $scope.serverIdLength will always be set to the length of the last serverId. That because it's a global variable and there is only one instance of it. This is why all your classes match. They all reference the same variable.
Instead like #dhilt suggested ditch the controller code and acccess the length in the dom:
ng-class="server.serverId.length > 12 ? 'col-md-3' : 'col-md-2'"
Try that:
ng-class="{'col-md-3':server.serverId.length > 12, 'col-md-2':server.serverId.length <= 12}"

split colon in view page using angularjs

I want replace colon in view page using angularjs.
For example i have some unique data like that
$scope.PlayerList =[{
"ID" : "111:Player",
"Name" : "Rasberry, Jackson (16U Blue)",
"Type" : null
}, {
"ID" : "112:Player",
"Name" : "Keller, Jacob",
"Type" : null
}]//This is my list
Here is my html
<div ng-repeat="item in PlayerList track by $index">
<input type="ceckebox" id="{{item.ID}}">
<!--Real out put is like that <input type="checkbox" id="111:Player"> -->
But i want to like <input type="checkbox" id="111Player">
</div>
I want to omit colon(:) in view page using angularjs without change $scope.layerList properties
If you have any idea please help me.........................
You can create a filter to achieve the results. Update code to following
<input type="ceckebox" id="{{item.ID | customText}}">
.filter('customText', function() {
return function ( input ) {
return input.split(":").join('');
};
})

How to handle JSON data using AngularJS?

Currently I have a json file that populates information to my chart. An example of this chart can be found here: http://marmelab.com/ArchitectureTree/. I also have a panel to the right which is meant to display the information of one of the charts node's when clicked. However I don't know how to do this.
Say if I had in my json array:
{
"name": "Blogs",
"url": "blogs.my-media-website.com/*",
"dependsOn": ["Wordpress MU"],
"technos": ["PHP", "Wordpress"],
"host": { "Amazon": ["?"] }
},
I would click on 'Blogs' in the chart and the 'url', 'dependsOn' etc would then be displayed in the panel. I'm sure this function uses AngularJS to do this. Can someone point me in the right direction on how to do this?
On click of Blogs call below function :
In your controller, try adding this function.
$scope.onClickOfBlogs = function(){
$http.get('Your_JSON_file_Path_here').success(function(response){
$scope.jsonObject= response;
}).error(function() {
console.log('error occured while getting JSON file');
});
};
in your Panel HTML : -
<div id ="info">
<span>URL : {{jsonObject.url}} </span>
<span>Name : {{jsonObject.name}} </span>
<ul>
Depends on :
<li ng-repeat = "depends in jsonObject.dependsOn"> <!-- to iterate on array you need ng-repeat -->
{{depends}}
</li>
</ul>
</div>
you will get the data from json file into your html panel.Hope this helps.
**
** : http://plnkr.co/edit/dbJ0bhHhvASffJU9liY6?p=preview

Categories