Print an array from a function inside Angular HTML - javascript

I'm doing an app where I print some cars (I receive them from the database) and in one column I have one string with multiple tags that are divided by commas, I made a function to receive that as an array of words and then print each word for make tags, but I don't really know how to call the function or how to do it because it's repeating multiple times when it shouldn't do that.
<!-- Category Card -->
<div *ngFor="let car of cars" class="col-md-4">
<div class="card-image-overlay m-auto" id="tags">
{{separar(car?.tags)}}
</div>
</div>
Then the code of the function "separar":
public separar(string) {
var palabras = [];
palabras = string.split(",");
for (var i = 0 ; i < palabras.length ; i++) {
document.getElementById("tags").innerHTML +=
("<span class='card-detail-badge'>" + palabras[i] + "</span>");
}
}
I'm getting this:
and it should only print 3 times those tags.
Probably is a mistake very easy but Im new to angular and my teacher doesn't know why it doesn't work. :(

Use ngFor to do it "the Angular way" 😉
getTags(tags: sring): string[] {
return tags.split(',');
}
<!-- Category Card -->
<div *ngFor="let car of cars" class="col-md-4">
<div class="card-image-overlay m-auto" id="tags">
<span class='card-detail-badge' *ngFor="let tag of getTags(car?.tags)">
{{tag}}
</span>
</div>
</div>

Try returning the HTML string from the template function instead.
Also, avoid common (sometimes "reserved") words for variables i.e use tagListStr instead of string.
public separar(tagListStr) {
return tagListStr
.split(",")
.map(tag => `<span class='card-detail-badge'>${tag}</span>`)
.join('');
}

Related

Loop not printing correct results on view

I'm trying make my Coordinates, Dispatcher and Captured At printout the correct totals that correspond to it's ID. Unfortunately, it's only assigning the first ID's totals in its HTML element. Having a bit of a braindead moment trying to fix this.
I know I'm missing something to identify the individual html instance, but I can't figure out how to make that happen.
HTML -
<div v-if="zoomLevel > 10" class="search-data">
<div><strong>Dispatcher:</strong> <span id="dispatcher">{{ dispatcher}}</span></div>
<div><strong>Lng/Lat:</strong> <span id="coordinates">{{ coordinates }}</span></div>
<div><strong>Captured At:</strong> <span id="capturedAt">{{ capturedAt }}</span></div>
</div>
JS -
export default {
data() {
return {
coordinates: '',
dispatcher: '',
capturedAt: '',
}
},
}
Method -
let totalTargets = Object.keys(e.source.data.features).length;
for (let i = 0; i < totalTargets; i++) {
console.log(e)
this.coordinates = e.source.data.features[i].geometry.coordinates.toString().replace("[", "").replace("]"," ").replace(",", ", ");
this.dispatcher = e.source.data.features[i].properties.name;
this.capturedAt = e.source.data.features[i].properties.capturedAt;
}
Console.log printout of method results
You need to iterate on the HTML, with v-for, create a reactive property to your list and can use like this:
<div v-if="zoomLevel > 10" class="search-data" v-for="(feature, index) in features" :key="index">
<div><strong>Dispatcher:</strong> <span id="dispatcher">{{ feature.dispatcher}}</span></div>
<div><strong>Lng/Lat:</strong> <span id="coordinates">{{ feature.coordinates }}</span></div>
<div><strong>Captured At:</strong> <span id="capturedAt">{{ feature.capturedAt }}</span></div>
</div>

How to search multiple words with javascript and Regex inside an html div?

I'm having a problem with a search system in JavaScript and RegExp. I already have the code working on the site, but it can only fetch a word, if I type two words it does not return results.
Here is an example of the currently running search field:
https://www.apaixonadosporhistoria.com.br/ficcao
When entering the name of the author in the field the divs that do not contain this name are hidden, and only appears the div with the name.
But like I said, the problem is the words in the correct order. And I would also need to search multiple words allowing several different orders, for example:
brenda,
vantrease brenda,
vantrease rickman,
brenda vantrease rickman
Below is my HTML and JavaScript code:
<input type="text" id="buscarautor" placeholder="Pesquise por autores" />
<div class="order-item autoritem">
<a href="https://www.apaixonadosporhistoria.com.br/ficcao-autor/50/gary-jennings">
<div class="col-md-3 col-sm-3 col-xs-6 sempaddingleft">
<div class="bloco-externo" data-nome="gary jennings" data-qtd="5" data-ano="2016-03-22 00:43:21" data-view="22">
<div class="bloco">
<div class="autor" style="background:url(https://www.apaixonadosporhistoria.com.br/img/ficcaoautor/ficcao_50_1752577805.jpg"></div>
<div class="fundolinha"><div class="linhacresce"></div></div>
<div class="nomeqtd"><h1>Gary Jennings<br/><small>5 livros</small></h1></div>
</div>
</div>
</div>
</a>
</div><!-- order-item -->
if (!RegExp.escape) {
RegExp.escape = function (s) {
return s.replace(/[\-\[\]{}()*+?.,\\\^$|#\s]/g, "\\$&")
};
}
if ($(".autoritem").length) {
var $rows = $('.autoritem');
$('#buscarautor').keyup(function () {
var regex = new RegExp(RegExp.escape($.trim(this.value).replace(/\s+/g, ' ')), 'i')
$rows.hide().filter(function () {
var text = $(this).find('.bloco-externo').data('nome').replace(/\s+/g, ' ');
return regex.test(text)
}).show();
});
$('#buscarautor').val('');
}

Using angular ng-repeat for multi-dimentional array

I'm currently working on a game and am trying to use NG repeat to dynamically add divs depending on how many latter and words there are. so for example if the answer to a queston in the game was "Clean Sheet" then i would want NG-Repeat to make the correct amount of columns so that it would say __ __ __ __ __ space __ __ __ __ __ then the user can fill them. Ive currently wrote this :
try{
//in this example presume $stateParams.answer is "clean sheet"
var answerArr = $stateParams.answer.toString().split(' ');
var finalLines = "";
$scope.mainWordHolder = [];
angular.forEach(answerArr, function(value, key) {
var amt = value.length;
$scope.amtofLetters=[];
for (var i=0; i<amt; i++) {
$scope.amtofLetters.push(i);
}
$scope.mainWordHolder.push($scope.amtofLetters);
$scope.amtofLetters = [];
});
console.log($scope.mainWordHolder);
}catch(e){console.log("error : "+ e);}
at this point my $scope.mainWordHolder is :
[ [ 0, 1, 2, 3, 4 ], [ 0, 1, 2, 3, 4 ] ]
which is exactly what i want so i know how many letters are needed for each word. How can i use ng-repeat to show this as divs so that i can create a keyboard and the user can enter keys like other popular games.
Ive tried this :
<div class="row">
<div ng-repeat="content in answerArr" class="col">
<div ng-repeat="contentt in mainWordHolder" class="col">
</div>
</div>
</div>
but i get nothing for some reason. Any help appreciated.
It looks like you're trying to reference answerArr in your ng-repeat, but answerArr is not stored on the scope.
When you use ng-repeat="content in answerArr", answerArr needs to be stored on the scope to be accessible in the HTML.
Try storing answerArr on your scope to be able to access it's contents via ng-repeat.
You need to iterate over the 'content' which represents the array in the whole array (the outer). Try this :
<div class="row">
<div ng-repeat="content in answerArr" class="col">
<div ng-repeat="contentt in content" class="col">
</div>
</div>
</div>

AngularJS: displaying an array of objects in separate rows

Let's say, I have an array of objects and I want to display it in several rows. Each row should consist of a specific number of objects. Basically, it should look like this:
<div class="row">
<div class="col-md-4">item</div>
<div class="col-md-4">item</div>
<div class="col-md-4">item</div>
</div>
<div class="row">
<div class="col-md-4">item</div>
<div class="col-md-4">item</div>
<div class="col-md-4">item</div>
</div>
...
I've implemented it with a very dirty trick, generating an additional array of numbers and iterating through it (4 is a number of objects in a row):
<div class="row titles-row" ng-repeat="row in outRange(series.length, 4)">
<project-preview class="col-md-3" ng-repeat="project in series" ng-if="$index < (row + 1)*4&& $index >= (row)*4"></project-preview>
</div>
and outRange function:
$scope.outRange = function(items_num, row_width) {
items_num = items_num > 0 ? items_num : 0;
var rows_num = Math.ceil(items_num / row_width);
return Array.apply(null, Array(rows_num)).map(function (_, i) {return i;});
};
It works, but I feel like there should be a better way to do it.
If this is just a matter of presentation, bootstrap (which it seems you might be using) will automatically put the other objects on a separate row when the sum of columns is more than 12 (it uses floats). If however the objects have significantly different sizes, this might not look so good indeed. Still, I would tend to leave this under control of CSS, rather than in javascript.
One approach would be to use a display: flexbox on the container, which should have the effect you want automatically. Lookup this CSS property to discover the true strength of flexbox.
If you really want to do it in javascript, you could have a template like:
<div ng-class='{row: $index % 4 == 0}' ng-repeat='...'>
<div class='col-md-4'>
..
</div>
</div>
This will generate extra divs, but that is likely acceptable.
Instead of outRange, use a filter to create chunks out of the series array. Lodash has a chunk method. Or you can implement one yourself.
Thanks for your ideas. I came up with this solution:
mainApp.filter('slice', function() {
return function(array, row_width, scope) {
if(array == undefined)
return;
if(scope.sliceResult != undefined)
return scope.sliceResult;
scope.sliceResult = [];
var rows_num = Math.ceil(array.length / row_width);
for(var i = 0; i < rows_num; i++) {
scope.sliceResult.push(array.slice(i * row_width, i * row_width + row_width));
}
return scope.sliceResult;
};
});
And here how I use it:
<div class="row titles-row" ng-repeat="row in series | slice: 4 : this">
<project-preview class="col-md-3" ng-repeat="project in row"></project-preview>
</div>
Still I don't like that I need to pass the scope inside the filter.

ng-repeat run as many times as integer parameter doesn't work in some cases

I want to run angular as many times as integer value passed to it.
EDIT: I simplified this example because originally I used function to return array based on number passed to it.
HTML
<body ng-app="userFilterModule">
<div class="container-fluid" ng-controller="UserfilterController as Ctrl">
<div class="row">
<div class="filter_tableTbody col-xs-12">
<div class="row filter_tableRow" ng-repeat="user in Ctrl.obj_users">
<!-- ... -->
<div class="col-xs-2">
<span class="filter_rateStars" ng-repeat="a in Ctrl.ratingArr| limitTo: user.rate">
★
</span>
<span class="filter_rateStars notActive" ng-repeat="a in Ctrl.ratingArr| limitTo: 5 - user.rate">
☆
</span>
</div>
</div>
</div>
</div>
</div>
</body>
And everything works fine if ratingArr contains numbers e.g.
app.controller('UserfilterController', function ($scope) {
this.int_male_counter = this.int_female_counter = 5;
this.str_sort_by = {
prop_name: 'f_name',
order: 'asc'
};
//problem starts here
this.ratingArr = [1,2,3,4,5];
this.obj_users = new Users(this.int_male_counter, this.int_female_counter).list;
this.fn_set_sorting = function (str) {
if (this.str_sort_by.prop_name === str) {
this.str_sort_by.order = this.str_sort_by.order === 'des' ? 'asc' : 'des';
} else {
this.str_sort_by.order = 'asc';
this.str_sort_by.prop_name = str;
}
this.obj_users.sortByObjKeyVal(this.str_sort_by.prop_name, this.str_sort_by.order);
};
this.fn_setlected_filter = function (str) {
return str === this.str_sort_by.prop_name;
};
this.fn_is_descending = function(){
return this.str_sort_by.order === 'des';
};
});
But when I change it to new Array(5) or ['','','','',''] or ['a','a','a','a','a']
I get error in console: Error: [ngRepeat:dupes] why?
Thanks!
By default, you cannot use identical values in the array processed by ng-repeat. Quoting the docs:
error:dupes
Duplicate Key in Repeater
Occurs if there are duplicate keys in an ngRepeat expression.
Duplicate keys are banned because AngularJS uses keys to associate DOM
nodes with items.
By default, collections are keyed by reference which is desirable for
most common models but can be problematic for primitive types that are
interned (share references).
As advised in the same docs, just use track by $index suffix (so that items will be keyed by their position in the array instead of their value) to resolve the issue:
<span class="filter_rateStars"
ng-repeat="a in Ctrl.ratingArr | limitTo: user.rate track by $index">

Categories

Resources