rendering the array values only works in the initialization in vue2? - arrays

I have worked on vue2 with a simple demo, there is an array with values, by clicking the button, the array values will be shuffled. However rendering the array in html doesn't change at all after the shuffling.
<template>
<div>
<div #click="random()" > random </div>
{{ selected11.length }}
<div class="flex flex-grow " v-for="(item,index) in selected11" :key="index" >
{{ item }} {{ index }}
</div>
</div>
</template>
<script>
export default {
name: 'Choice',
data() {
return {
selected11:[],
}
},
created() {
this.selected11 = ['A', 'B', 'C', 'D','E'];
},
methods: {
random(){
console.log( 'random',this.selected11 );
this.selected11 = this.shuffle( this.selected11 );
console.log( this.selected11 );
},
shuffle(a) {
var j, x, i;
for (i = a.length - 1; i > 0; i--) {
j = Math.floor(Math.random() * (i + 1));
x = a[i];
a[i] = a[j];
a[j] = x;
}
return a;
}
}
}
</script>

The issue is in your shuffle method where reassignment of keys with values from key positions of its own referenced self is self-destructive and is causing a silent reactive fail.
The only way I can think of describing this is like a Wormhole is traveling into its self, in this circular event that warps its self out of existence...
You need to shuffle a clone of the original object and return this shuffled clone so it replaces the original object, otherwise the array eats its self.
shuffle(a) {
let j, x, i;
let shuffle = structuredClone(a)
for (i = shuffle.length - 1; i > 0; i--) {
j = Math.floor(Math.random() * (i + 1));
x = shuffle[i];
shuffle[i] = shuffle[j];
shuffle[j] = x;
}
return shuffle;
}

Related

Call a function from a dynamic html string IONIC

I'm trying to call a function through a dynamic string in html like this
(this.salva(i)): for (let i = 1; i < 41; i++) {
for (let y = 0; y < budini.length; y++) {
contains = this.diseases["M_" + i].g.includes(budini[y])
if (contains) {
output.innerHTML += `
<ion-card class=>
<ion-card-header>
<b>${this.diseases["M_" + i].m} </b>
</ion-card-header>
<ion-card-content>
<div class="fav">
<input type="checkbox" id="heart${i}" (click)=${this.salva(i)}>
<label for="heart${i}"></label><br><br>
Generi:
</div>
</ion-card-content>
</ion-card>
`;
break;
}
}
}
The problem is that the following function in the is not called:
salva(elementoCliccato: number) {
console.log("elementoCliccato")
console.log(elementoCliccato)
let cliccato = <HTMLInputElement>document.getElementById("heart" + elementoCliccato);
console.log(cliccato.checked)
if (cliccato.checked == true) {
var elementoSalvato;
elementoSalvato = this.diseases["M_" + elementoCliccato];
console.log(elementoSalvato)
}
}
So there is a way to call a function from a dynamic html string IONIC?

push object to array of arrays vue re-rendering failing

I have this weird issue where I can't seem to push an object to an array of arrays.
I am able to log the value of groups....but I can't update it.
here's my function to push to the groups array under a given set of conditions
calcExclusion: function(){
this.hideExclusionGroups = true //hides the exclusion groups from app before calculations
for(var i = 0; i < this.exclusionGroups.length; i++){
if(this.numberOfGroups < this.exclusionGroups.length){
alert('could not calculate, there are more exclusion groups than groups')
return
}
for(var j = 0; j < this.exclusionGroups[i].students.length; j++){
if(this.exclusionGroups[i].students.length == 1){
alert ('could not calculate, groups must be bigger than 1')
return
}
//console.log('group number', g,'student to add',this.exclusionGroups[i].students[j])
if(j < this.numberOfGroups){
this.groups[i].push(this.exclusionGroups[i].students[j].first_name)
console.log(this.groups[i])
}
}
}
},
here is where I render the data
<div v-for="(group, index) in groups" class="d-inline-block bg-white p-2 m-2 border rounded">
<span>Group {{ index + 1 }}</span>
<ul>
<li class="groupItems" v-for="student in group">
{{ student.first_name }}
<input type="hidden" :name="'group['+index+']'" :value="student.id">
</li>
</ul>
</div>
I am able to edit 'groups' to some extent but groups is referencing the computed prop here
computed: {
groups: function () {
if(! Number.isInteger(this.numberOfGroups)) {
console.log('mal');
return [];
}
const array = [];
for (let j = 0; j < this.numberOfGroups; j++) {
array[j] = [];
}
let i = 0;
this.students.forEach((student) => {
const x = i % this.numberOfGroups;
if(student.include === false){
array[x].push(student);
}
i++;
});
return array;
},
},
You are updating the results of a computed property. The result is not reactive, that's why you see that your code is updating the groups array, but you don't see any changed in the DOM.
You need to move the logic from calcExclusion inside the computed method for groups.

How to use conditional to generate element on the page

for (var k = 0; k < 10; k++) {
if (k % 2 === 0) {
weatherText = <div className="in_break">
}
weatherText += <div className="eachD" key={k}>
<div>
{
countIt === 0 ? (currDate.getHours() > 12 ? "Tonight" : "Today") : dayOfWeek[weekDay]
}
</div>
<div>
{
getDate
}
</div>
<div>
{
<ReturnIcon />
}
</div>
</div>
if (k % 2 === 0) {
weatherText += </div>
}
}
What I am looking to do is group all the eachD by two inside the `in_break' div
But I keep getting:
Parsing error: Unexpected token 'weatherText = </div>'
This is the layout:
in_break
eachD
eachD
in_break
eachD
eachD
in_break
eachD
eachD
...
Please help me resolve my issue
UPDATED
I hope this find it's way to your demand:
setWeatherTextItems = (countId, currDate, dayOfWeek, weekDay, getDate) => {
// you make sure all the variables such like countId and currDate are available inside this function.
const items = [];
for (var k = 0; k < 10; k++) {
items.push(
<div className="eachD" key={k}>
<div>
{countIt === 0
? currDate.getHours() > 12
? "Tonight"
: "Today"
: dayOfWeek[weekDay]}
</div>
<div>{getDate}</div>
<div>{<ReturnIcon />}</div>
</div>
);
}
return items;
}
renderInBreak = () => {
const items = this.setWeatherTextItems();
const inBreakItems = [];
let breakBlock = [];
let newBreak = false;
items.forEach((textItem, index) => { //1
if(!newBreak) {
breakBlock.push(textItem);
if(index + 1 === items.length){
inBreakItems.push(breakBlock);
}
} else {
inBreakItems.push(breakBlock);
breakBlock = [];
breakBlock.push(textItem);
//without this condition check, the last element will be left out of an odd array length
if(index + 1 === items.length) {
inBreakItems.push(breakBlock)
}
}
if(index % 2) newBreak = true; //false
else newBreak = false; //false
});
return inBreakItems.map(twoTextWeatherItems => (
<div className="in_break">
{twoTextWeatherItems}
</div>
))
}
render(){
<div>
{this.renderInBreak()}
</div>
}
OLD
React is supposed to handle things differently, maybe this will work:
Define a method in your component that will set your items:
setWeatherTextItems = (countId, currDate, dayOfWeek, weekDay, getDate) => {
// you make sure all the variables such like countId and currDate are available inside this function.
const items = [];
for (var k = 0; k < 10; k++) {
items.push(
<div className="eachD" key={k}>
<div>
{countIt === 0
? currDate.getHours() > 12
? "Tonight"
: "Today"
: dayOfWeek[weekDay]}
</div>
<div>{getDate}</div>
<div>{<ReturnIcon />}</div>
</div>
);
}
return items;
}
in your render method, or where you are willing to render these items:
render(){
<div className="in_break">{this.setWeatherTextItems()}</div>
}
Read more about how to render things in a loop.
You can add the conditions you want inside the for loop, or where it makes sense to you.
Not sure if the logic would work in a react environment but as far as I can see from your plain code when you are going to add the 'in_break' div aren't you just assigning the whole whetherText again instead of joining text to it?
Shouldn't this:
if (k % 2 === 0) {
weatherText = </div>
}
be written like this?
if (k % 2 === 0) {
weatherText += </div>
}
Edit following the typo correction:
I tried to run your code on codepen to have a quicker and easier understanding on how to find a solution.
I created an helper function with your code then I returned
<div className="Container" dangerouslySetInnerHTML={{__html: weatherText}}></div>
This enables you to have the result you are looking for. Only the even elements have the 'in_break' class.
Hope this helped and let me know if this is not correct.
Codepen: https://codepen.io/dpgian/pen/EBzRmX

How to dynamically use object property as width in AngularJS (in ng-repeat)?

I cannot get the object's property to be read in ng-style(shape.radius || shape.length). I can't even get 1 to work at the moment, but would like to have an or statement included. Similar to my ng-class.
There is a button to generate shapes, and the shapes were created with a random size. Here is my code:
html:
<div ng-controller='ShapeController as sc'>
<div>
<p><input type="submit" value="Generate Random Shapes" ng-click="sc.generateShapes()"/></p>
<div ng-repeat="shape in sc.shapes">
<div class="shape" ng-class="{circle: shape.radius, square: shape.length}" ng-style="{'width': shape.length}"></div>
</div>
</div>
</div>
script:
var app = angular.module('app', []);
app.controller('ShapeController', function(){
var vm = this;
vm.shapes = [];
vm.randomShapes = [];
vm.width = 30;
function createCircle(radius) {
let circle = new Circle(radius);
vm.shapes.push(circle);
} // end createCircle
function createSquare(length) {
let square = new Square(length);
vm.shapes.push(square);
} // end createSquare
vm.generateShapes = function() {
let times = 50
for (let i = 0; i < times; i++) {
createCircle(getRandomNumber());
}
for (let i = 0; i < times; i++) {
createSquare(getRandomNumber());
}
sort(vm.shapes);
console.log(vm.shapes);
}; // end generateShapes
}); // end controller
function sort(arr) {
arr.sort(function(a,b){
return b.getArea() - a.getArea();
});
} // end sort function
function getRandomNumber() {
return Math.random() * (100-1) + 1;
}
width should be either in px(some unit like em, pt, etc) or %
ng-style="{'width': shape.length + 'px'}"

cannot read property of -1 in ReactJS multidimensional grid

I'm at my witsend with this problem. I'm building Conway's game of life and right now I'm trying to find neighbors(cells that are on top, to the bottom, and on the sides of the target cell). When I console log my function (basically to find the neighbors), I get values for the bottom and middle rows and all columns but for the top row I get "Cannot read property '-1' of undefined". Sometimes it will return "cannot read property of 'r' of defined" as well. I'm confused because I get return values when i console log both row (r) and columns (c). I'm also curious as to why I don't see this same error message when dealing with my columns. The messages on developer tools are very cryptic. I've spent quite a bit of time trying to figure this out but I'm truly stuck. Any help would be much appreciated.
I tried to do a JSbins: https://jsbin.com/bapazem/edit?html,css,js,output but its not liking the construction of my react components. You can see these areas clearly on my codepen: http://codepen.io/tbraden30/pen/AXgVNQ. Just click the play button and dev tools
Thanks in advance for your help
function randomGrid() {
var gridHeight = 20,
gridWidth = 20,
gridContainer = [];
for (var r = 0; r < gridWidth; r++) {
var row = [];
for (var c = 0; c < gridHeight; c++) {
row.push({
alive: Math.random() < 0.2,
neighbors: 0,
r: r,
c: c,
coords: [r, c]
});
}
gridContainer.push(row)
}
return gridContainer;
}
function isWithinBounds(cell) {
if (cell.r >= 0 && cell.r < 20 && cell.c >= 0 && cell.c < 20) {
return true
}
}
var grid = randomGrid();
var Board = React.createClass({
getInitialState: function() {
return {
cellLocation: randomGrid()
};
},
updateCells: function(r, c) {
var grid = this.state.cellLocation;
for (var r = 0; r < 20; r++) {
for (var c = 0; c < 20; c++) {
var cell = grid[r][c];
//console.log('cell', cell)
cell.neighbors = 0;
var isAlive = cell.alive;
var bottomLeft = grid[r + 1][c - 1],
bottomMiddle = grid[r + 1][c],
bottomRight = grid[r + 1][c + 1],
middleLeft = grid[r][c - 1],
middleRight = grid[r][c + 1],
topLeft = grid[r - 1][c - 1], **//problematic**
topMiddle = grid[r - 1][c], **//problematic**
topRight = grid[r - 1][c + 1];**//problematic**
/* if (isWithinBounds(bottomLeft) && isAlive) {
cell.neighbors++;
}
if (isWithinBounds(bottomMiddle) && isAlive) {
cell.neighbors++;
}
if (isWithinBounds(bottomRight) && isAlive) {
cell.neighbors++;
}
if (isWithinBounds(middleLeft) && isAlive) {
cell.neighbors++;
}
if (isWithinBounds(middleRight) && isAlive) {
cell.neighbors++;
}
if (isWithinBounds(topLeft) && isAlive) {
cell.neighbors++;
}
if (isWithinBounds(topMiddle) && isAlive) {
cell.neighbors++;
}
if (isWithinBounds(topRight) && isAlive) {
cell.neighbors++;
}*/
console.log('TR', topRight)
}
}
return cell;
},
render: function() {
return (
<div className='container grid_body'>
<CellMatrix grid={this.state.cellLocation}/>
<button type='button' onClick={this.updateCells} className='play'>Play</button>
</div>
)
}
}, this)
var CellMatrix = React.createClass({ //cells conglomerated into a grid
render: function() {
var fillCells = [],
grid = this.props.grid,
grid = grid.reduce((a, b) => a.concat(b)) //flattens the array.
grid.map(function(cellObject, index) {
fillCells.push(<Cell alive={cellObject.alive} r={cellObject.r} c={cellObject.c} coords={cellObject.coords} index={index} neighbors={this.updateCells}/>)
// console.log('fillcells', fillCells)
}, this)
return (
<div>
{fillCells}
</div>
)
}
})
var Cell = React.createClass({ //individual cell
render: function() {
return (
<td className={this.props.alive}
index={this.props.index}
coords={this.props.coords}
r={this.props.r}
c={this.props.neighbors}
neighbors={this.props.neighbors}
>
{this.props.children}
</td>
)
}
})
ReactDOM.render(<Board/>, document.getElementById('content'))
it sounds like an off by 1 error. when you generate the grid, you go from index 0..19, yet in the updateCells function you have a loop that sets c = 0, then subtracting 1 from it, meaning youre trying to access grid[-1][-1] when r and/or c is 0 (probably not what youre trying to do). then the fatal error likely occurs when r is 19 and c is 0, and you add one to r and subtract 1 from c. you end up accessing grid[20][-1] and since grid[20] is undefined, you get the error Cannot read property '-1' of undefined

Resources