How to populate data from first array on randomly selected card? - javascript

how to populate data from first array on randomly selected card?
I want to make a random card in Angular, where every time I select the first card to click it will take the first value from the array and the other cards will be filled automatically with other array values. and click can only be done once. thank you.
here my code sandbox
here my angular component:
export class AppComponent {
arrayData: any = \["one", "two", "three"\];
value: any = "";
clicker() {
this.value = this.arrayData\[0\];
}
}
and this for html:
<div class="card" \*ngFor="let v of arrayData" (click)="clicker()"\>
<label\>{{value}}\</label\>
<p>
How to get arrayData[0] on card selected and filled in other card with
arrayData[1] and arrayData[2] then disable click
</p>
i hope any one can help me to solve this problem!!! thanks you.

You are looping the array in HTML, but in the loop, you are outputting one value from this.value three times.
Just loop the array, and use its elements to display, but only after a card was clicked. (The json pipe helps if the elements are objects...)
<div class="card" *ngFor="let v of arrayData" (click)="clicker()">
<label *ngIf="clicked">{{v | json}}</label>
</div>
<p>
How to get arrayData[0] on card selected and filled in other card with
arrayData[1] and arrayData[2] then disable click
</p>
and in TS:
clicked = false;
clicker() {
this.clicked = true;
}

You show as many cards as the length of array - ok. On each card you show value of the variable value - the same variable.
<div class="card" *ngFor="let v of arrayData" (click)="clicker()">
<label>{{value}}</label>
</div>
You have no association of card with values.
It would be helpful to add:
(You can also do better - programmatically create as many array objects as arrayData length)
cards: any = [
{ id: 1, value: null },
{ id: 2, value: null },
{ id: 3, value: null }
];
Now for each card you have the option to assign a value.
In template you can display:
<div
class="card"
*ngFor="let card of cards; let i = index"
(click)="onCardClick(i)"
>
<label>{{ card.value }}</label>
</div>
{{ card.value }} - value of unique card.
Pay attention to the *ngFor="let card of cards; let i = index" - we have an (incremented) index here - information about which card was clicked.
In onCardClick method we check whether the user has already performed such an operation.
onCardClick(index: number) {
if (!this.shuffled) {
this.clicker(index);
}
}
In else you can show the user an alert or whatever to let them know they've already done it.
If not, call the method clicker.
clicker(index: number) {
let arrayDataIndex = 1;
this.cards.forEach((card: any, idx: number) => {
if (index === idx) {
card.value = this.arrayData[0];
} else {
card.value = this.arrayData[arrayDataIndex];
arrayDataIndex++;
}
});
this.shuffled = true;
}
In foreach loop through the next elements of cards. If element has the same index as clicked card, assign first value of arrayData. Otherwise assign arrayData[1], arrayData[2]...
At least, this.shuffled = true, that the operation cannot be performed again.
I hope I understood what you wanted to accomplish :)
See working code
https://codesandbox.io/s/loving-wind-gku7vl

Related

How to know selected div ? Angular

I need to know which div is selected.
Check my code:
<divdsadsadasda
toggle(i) {
console.log(i) // i got index
}
I need to know which div is selected and return values from clicked item.
Instead of (click)="toggle(i)" replace it with (click)="toggle(training)" tht way you'll know which of the trainingExercises was selected.
<div *ngFor="let training of data.trainingExercises; let i = index;">
...
<div (click)="toggle(training)">
...
</div>
</div>

Conditionally disable button in ngFor in Angular 7

I am trying to disable buttons that the logged in user have voted on, however, when I use the disabled directive inside my ngFor (in the example below) all of the buttons are disabled, not just the items that include the logged in user. My goal is to check to see if an array contains the current user's uid, if so disable the button. How can I achieve this? Thanks in advance
compontent.ts:
this.itemsCollection = this.afs.collection('food', ref => ref.orderBy('voteCount', 'desc'));
this.items = this.itemsCollection.snapshotChanges().pipe(
map(actions => actions.map(a => {
const data = a.payload.doc.data();
const id = a.payload.doc.id;
this.afAuth.authState.subscribe(user => {
if(user) {
this.user = user.uid;
if (data.votedBy.includes(user.uid)){
console.log(id);
console.log('you already voted');
this.disabledButton = true;
return false;
}
else {
this.disabledButton = false;
}
}
});
return { id, ...data };
}))
);
html:
<div class="firestoreLoop" *ngFor="let item of items | async" >
<div class="container1">
<div class="card">
<div class="card-body">
<p>{{item.voteCount}}</p>
<p>{{item.id}}</p>
<p>{{item.votedBy}}</p>
<p>{{user}}</p>
</div>
<button type="button" id="item.id" class="btn"(click)="upvote(item.id)" [disabled]="disabledButton">Upvote</button>
</div>
</div>
</div>
Edit: I got the desired result by adding *ngIf= "user != item.votedBy" to the button. Thanks for the help gentleman.
best way for you is to add disabledButton as a property of item in items array,
and then the [disabled] on the button should be [disabled]="item.disabledButton".
And then you can control which item should be disabled by simply identifying the user and setting its corresponding item's disabledButton property to true otherwise false

Remove deselected checkbox value from Array using Angular

This is simple one but i still somehow couldn't get it to work.
I have default value checked, checkbox. So when edit, of course the default value is chosen, but later I want to remove the default value and choose another value. Here it is
array1=[] //empty
After I check a checkbox, it will inserted to this array
array1=["sun"]
If I select 3 values (array1["sun","stars","moon"])
but I deselect the first selection (the default selection), it will be still in the array. (array1["sun","stars","moon"]) but I the expected result is this:
array1["stars","moon"]
No more first selection. So how to remove deselected value from array using Angular/Javascript?
I have tried use splice, remove and set
Same thing developed and used in project :
Template side :
<label *ngFor="let hobby of hobbies" #checkbox class="mdl-checkbox mdl-js-checkbox">
<input type="checkbox" name="hobbies" [value]="hobby"
(change)="populateMyHobbies(hobby,$event.target.checked)" class="mdl-checkbox__input">
<span class="mdl-checkbox__label">{{hobby}}</span>
</label>
Component Side :
selectedHobbies = [];
populateMyHobbies(value , status:boolean)
{
if(this.selectedHobbies.indexOf(value) === -1 && status)
{
this.selectedHobbies.push(value);
}
else if(!status)
{
let index = this.selectedHobbies.indexOf(value);
this.selectedHobbies.splice(index, 1);
}
}
Here selectedHobbies will give you what you want.
Have to change just name as per your app.
i used it once in my project. change the code according to your need. logic is same.
html part
<input type="checkbox" value="{{category._id}}" (change)="pushpopcategory(category._id)" id="{{category._id}}">
component code
pushpopcategory(value) {
if ((<HTMLInputElement>document.getElementById(value)).checked) {
this.categoryAdd.push(value);
} else {
let indexx = this.categoryAdd.indexOf(value);
this.categoryAdd.splice(indexx, 1);
}
}

Angular JS: Add and remove terms from checkboxes in ng-repeat?

I have a miller column constructed in Angular and Bootstrap.
http://codepen.io/smlombardi/pen/WGwGbY
In the second column, clicking the word (link) opens the third column, but I need to have the checkbox add that word to an array of search terms.
If the checkbox is UN-checked, I need to remove that word from the array of search terms. As you can see in the pen, I have the adding part working, but un-checking the box adds the word again.
I realize what I need to do is somehow check the state of the checkbox and if it's true add the word and if it's false check the array for the word (string) and pop it out of the array.
I can't figure out how to check only the checkbox that was clicked.
<div class="col-xs-3 inner-column">
<div class="panel panel-default">
<div class="list-group">
<div class="list-group-item" ng-class="{active: $index === pmt.millercolumn.level1Selected }" ng-repeat="level1 in pmt.millercolumn.level1 track by $index">
<input type="checkbox" ng-model="activeSearchTerm" ng-change="pmt.change($index)" id="ng-change-example1" />
<a href="" ng-click="pmt.getSublevel2($index)" >
{{level1.name}}
<i class="pull-right fa fa-angle-right fa-lg"></i>
</a>
</div>
</div>
</div>
the ng-change on the checkbox calls:
_this.change = function (index) {
var searchTerm = _this.millercolumn.level1[index].name;
_this.searchTerms.push(searchTerm);
};
It looks like you're thinking in a jquery mindset where you need to handle events when something changes. An easier way would be to make each checkbox correspond to an item in the array, so the ng-model would be something like level1.isSelected. Then, to construct your search terms array, use scope.$watch and pass true as the 3rd argument to deep watch your array of items. When a checkbox is checked, your watch will be called and you can reconstruct the search terms array by plucking the terms of the list items that are selected.
Add this code in place of your _change function it works for sure
_this.change = function (index) {
console.log('Clicked on', _this.millercolumn.level1[index].name);
var searchTerm = _this.millercolumn.level1[index].name;
var searchIndex = _this.searchTerms.indexOf(searchTerm);
if (searchIndex == -1) { // If new push
_this.searchTerms.push(searchTerm);
}
else { // Else remove item
_this.searchTerms.splice(searchIndex, 1);
}
console.log(_this.searchTerms);
};
Working codepen demo : http://codepen.io/krishcdbry/pen/EgKgBv
You're running the same code no matter if the checkbox is checked or not. Try something like this:
_this.change = function (index, checked) {
var searchTerm = _this.millercolumn.level1[index].name;
if(checked){
_this.searchTerms.push(searchTerm);
}
if(!checked){
_this.searchTerms.splice(searchTerm);
}
};
FWIW, this is what I did, which works:
<input type="checkbox" ng-model="level1.isSelected" ng-change="pmt.change($index, level1)" id="mycb" />
_this.change = function (index, item) {
if (item.isSelected) {
_this.searchTerms.push(item.name);
} else {
var termToRemove = item.name;
for (var i = _this.searchTerms.length - 1; i >= 0; i--) {
if (_this.searchTerms[i] === termToRemove) {
_this.searchTerms.splice(i, 1);
}
}
}
};

Angular - using the same form to Create and Update

I have a really simple CRUD app for managing music albums. Just two fields are tracked, title and artist.
In this example, the dropdown shows a list of albums, and if I fill out the form and click Save it will be added to the list.
In the second example, selecting an album will populate the form so it can be edited and updated.
My question is, is there a way to get both functionality in the same form? Sure I could create two identical forms and have them do slightly different things, but given they're operating on the same data, it would be nice if when a current_album is selected, it updates, and when "New album..." is selected, it creates.
The major roadblock seems to be value vs ng-model. I can set the value so it populates when I pick an item from the <select> OR I can set an ng-model="newAlbum", but not both to my knowledge.
You shouldn't be using the value attribute with ng-model. This is a very bad practice.
What I would suggest is to use ng-change on your list and keep a cloned object with the editing value.
$scope.onChange = function() {
if ($scope.currentAlbum) {
$scope.editing.title = $scope.currentAlbum.title;
$scope.editing.artist = $scope.currentAlbum.artist;
} else {
$scope.editing = {};
}
};
The all you need to do when saving is checking is it a new object or not:
$scope.addOrSaveAlbum = function() {
if ($scope.currentAlbum) {
$scope.currentAlbum.title = $scope.editing.title;
$scope.currentAlbum.artist = $scope.editing.artist;
} else {
$scope.albums.push({ title: $scope.editing.title, artist: $scope.editing.artist });
}
$scope.editing = {};
};
See http://jsfiddle.net/4Zeuk/12/
(thank you to Wawy to point out ng-change instead of $scope.$watch)
You can indeed get both functionality without the need of two different forms, but you can't use the same object in the scope in ng-model for both select and form fields.
But what you can do is have two different objects in the scope, one that contains the value of the selected item and the other will contain either a new instance of an album or a copy of the selected one. Then when you click the save/update button, based on the id of the object in the form you can decide if you need to save or modify the album collection.
Here is one way of doing what I've just explained:
<div ng-app="albumShelf">
<div ng-controller="MainCtrl">
<div style="float:left;">
<select ng-options="b.title for b in albums" ng-model="current_album" ng-change=updateForm()>
<option value="">Choose album...</option>
</select>
</div>
<div style="float:left;">
<form>
<input type="text" ng-model="newAlbum.title">
<br>
<input type="text" ng-model="newAlbum.artist">
<br>
<input type="submit" value="{{ current_album ? 'Update' : 'Save' }}" ng-click="modifyAlbumCollection()">
</form>
</div>
</div>
var albumShelf = angular.module('albumShelf', [/*'ngResource'*/])
.controller('MainCtrl', ['$scope', function($scope/*, albumFactory*/) {
//$scope.albums = albumFactory.query();
$scope.albums = [
{ id: 1, title: 'Disorganized Fun', artist: 'Ronald Jenkees' },
{ id: 2, title: 'Secondhand Rapture', artist: 'MS MR' }
];
$scope.modifyAlbumCollection = function() {
if ($scope.newAlbum.id !== null) {
//We are modifying an existing album
var i, found = false;
for (i = 0; i<$scope.albums.length && !found; i++) {
if ($scope.albums[i].id === $scope.newAlbum.id) {
$scope.albums[i] = angular.copy($scope.newAlbum);
found = true;
}
}
} else {
//We are adding a new album to the collection
$scope.newAlbum.id = $scope.albums.length;
$scope.albums.push(angular.copy($scope.newAlbum));
$scope.newAlbum = { id: null, title: '', artist: '' };
}
};
$scope.updateForm = function() {
if ($scope.current_album) {
//Copy the information from the selected album into the form.
$scope.newAlbum = angular.copy($scope.current_album);
} else {
//Clear previous album info.
$scope.newAlbum = { id: null, title: '', artist: '' };
}
};
}])
//.factory('albumFactory', function($resource) {
// return $resource('/albums/:albumId.json', { albumId: '#id' }
// );
//});
Here is the jsfiddle
In my opinion it's more clear if you use a ng-change in the select rather than a $watch on the ng-model value. Because what you want is update the form when a new value is selected from the dropdown rather than watching for changes on the object in the $scope.

Categories