How to add new row from last using swimlane/ngx-datatable - angular7

Tried to add new row to swimlane/ngx-datatable but not working properly. I want to add new row to from last but in my code it is adding on that same row.If you see my stackblitz demo you can understand my issue.Click on addnewrow option and see it.I do not know how to combine rowData and data to add the new row in the table. How to resolve this issue.
Note: We can use the addNewRow option(button or link) outside of table.
app.component.html:
<ng-template #buttonsTemplate let-row="row" let-value="value" let-rowIndex="rowIndex">
<div class="actions">
<a href="javascript:void(0)" (click)='addNewRow(row,rowIndex)'> AddNewRow </a>
</div>
</ng-template>
app.component.ts:
addNewRow(data, rowIndex) {
//Copy the data
let rowData = {
name: "Beryl Rice New",
gender: "Male",
company: "Velity",
actions: ""
};
//rowData.BATCH_CODE = "";
//rowData.qty = 0;
this.rows.splice(rowIndex, 0, rowData);
this.rows = [...this.rows];
}
Demo: https://stackblitz.com/edit/angular-ymttep?file=app%2Fapp.component.ts

Please update your addNewRow() method
this.rows.splice(rows.length, 0, rowData);

Related

mat-checkbox: The checkboxes are checked by default and affect each other?

I have 7 checkboxes in my RactiveForm. This is how I am generating them using FormArray:
ts:
weekDaysDe: string[] = ['Mo', 'Di', 'Mi', 'Do', 'Fr', 'Sa', 'So'];
taskForm: FormGroup = this.formBuilder.group({
weekDays: this.formBuilder.array([
this.formBuilder.control(false),
this.formBuilder.control(false),
this.formBuilder.control(false),
this.formBuilder.control(false),
this.formBuilder.control(false),
this.formBuilder.control(false),
this.formBuilder.control(false),
]),
});
html:
<!-- weekdays -->
<div class="task-form-control" *ngIf="isRecurrent">
<mat-label>Tage</mat-label>
<div class="weekdays" formArrayName="weekDays">
<mat-checkbox
*ngFor="
let weekDay of taskForm.get('weekDays').value;
let i = index
"
color="primary"
labelPosition="before"
[formControlName]="i"
>{{ weekDaysDe[i] }}</mat-checkbox
>
</div>
</div>
The checkboxes are rendered as expected but there are two problems:
They are all checked at first
They check/uncheck each other. For example when I check the first one the last one also get checked
What have I done wrong?
In template, Use Form Array controls to iterate over with *ngFor.
Try this:
<div class="weekdays" formArrayName="weekDays">
<mat-checkbox *ngFor="
let weekDay of weekDaysArray.controls;
let i = index
" color="primary" labelPosition="before" [formControlName]="i">{{ weekDaysDe[i] }}
</mat-checkbox>
</div>
Access the FormArray control with a getter method like this.
componen.ts
get weekDaysArray() : FormArray{
return this.taskForm.get('weekDays') as FormArray;
}
Example

some reason Cannot read property addEventListener of null

I got this error. I tried to dinamicly add some html tags by JS.. And there is a ID name is well what I need for addEventListener. But I dont know how to fix it.. If I change '#answer-' + i to .answers is working.. But this is not solution because I could click for any button without get the clicked ID..
Questions.prototype.displayQuestion = function() {
let answer = [];
questionDOM.innerHTML = this.question;
let correct = this.correct;
for(let i = 0; i < this.answer.length; i++){
answer.push(
`
<div id="answer-${i}" class="answer">
<h5>${this.answer[i]}</h6>
<div class="check"></div>
</div>
`
);
document.querySelector('#answer-' + i).addEventListener('click', function() {
if(i === correct) {
document.querySelector('#answer-' + correct).classList.add('animate__animated', 'animate__heartBeat');
} else if (i !== correct) {
document.querySelector('#answer-1').classList.add('animate__animated','animate__headShake')
}
})
}
answerDOM.innerHTML = answer.join('');
}
index.html
<body>
<div class="container">
<div class="question">
<div class="questionbox animate__animated animate__bounce">
<h2 id="question"></h2>
</div>
</div>
<div class="answers"></div>
</div>
<script src="app.js"></script>
You are pushing to your answers array but not actually adding the nodes to the dom. You want to do something like document.body.innerHTML += answer[i] before you try to get the element by id. I can also see that your loop won't execute because the length of answer is initially zero before you add to it within the loop. You need to add to answer before the loop or change the loop condition to <= this.answer.length <--- but that is an infinite loop

GAS PropertiesService to Save and Return Sort Order

QUESTION
How can I use PropertiesService to store an array from index.html, send the array to code.gs, and return the array in index.html?
SPECIFIC CASE
In a Google Web App, I have a group of sortable lists (made using JQuery UI Sortable). I want to save the most recent order/position of each li. I'm attempting to have that order/position "persist" when the page is refreshed or closed.
EXAMPLE
If you see the default Sortable, you could change the order of the items. If you refreshed the page, or closed it and return, the items would be in their original order.
WHERE I'M HAVING TROUBLE
I am able to get the array to show up in the console, but I don't know how to get it back to code.gs. I think I am now, but I'm not sure. Beyond that, I don't know how to "read" that PropertiesService so that the array is returned to index.html. I'm not really sure what I'm doing so if someone could slow walk me it would be appreciated!
ALTERNATIVES
I also looked into writing directly to the spreadsheet where the values originate. I'm not really sure how to do that either. I made some attempts, and was able to get "undefined" as a value in a spreadsheet cell.
FULL CODE (note: the list items are formed using an array, so they will not show up here): https://jsfiddle.net/nateomardavis/Lmcjzho2/1/
PARTIAL CODE
code.gs
function doGet() {
return HtmlService.createHtmlOutputFromFile('index');
}
function webAppTest() {
getTeamArray();
}
function getTeamArray() {
var ss = SpreadsheetApp.getActive();
var sheet = ss.getSheetByName('TEST');
var range = sheet.getRange(2, 1, 1000, 1);
var values = range.getValues();
var teamsArray = [];
for (var i = 0; i < values.length; ++i) {
teamsArray.push(values[i][0]);
}
var uniqueArray = [];
uniqueArray.push(teamsArray[0]);
for (var i in teamsArray) {
if ((uniqueArray[uniqueArray.length - 1] != teamsArray[i]) && (teamsArray[i] !== "")) {
uniqueArray.push(teamsArray[i]);
}
}
return uniqueArray;
}
function savePositions(myProperty, positions) {
PropertiesService.getScriptProperties().setProperty("myProperty", JSON.stringify(positions));
};
function getPositions() {
var returnedObj = PropertiesService.getScriptProperties()
};
index.html
<body>
<div id="myList" class="connectedSortable">MY LIST</div>
<table id=table1>
<div id="team1">
<p>TEAM 1</p>
<br>
<div id="group" v>SELECTED</div>
<ul id="team1s" name='team1s' class="connectedSortable"></ul>
<div id="group">ALTERNATE</div>
<ul id="team1a" name='team1a' class="connectedSortable"></ul>
</div>
</table>
<table id=table2>
<div id="team2">
<p>TEAM 2</p>
<br>
<div id="group" v>SELECTED</div>
<ul id="team2s" name='team2s' class="connectedSortable"></ul>
<div id="group">ALTERNATE</div>
<ul id="team2a" name='team2a' class="connectedSortable"></ul>
</div>
</table>
<table id=table3>
<div id="team3">
<p>TEAM 3</p>
<br>
<div id="group" v>SELECTED</div>
<ul id="team3s" name='team3s' class="connectedSortable"></ul>
<div id="group">ALTERNATE</div>
<ul id="team3a" name='team3a' class="connectedSortable"></ul>
</div>
</table>
<table id=table4>
<div id="team4">
<p>TEAM 4</p>
<br>
<div id="group" v>SELECTED</div>
<ul id="team4s" name='team4s' class="connectedSortable"></ul>
<div id="group">ALTERNATE</div>
<ul id="team4a" name='team4a' class="connectedSortable"></ul>
</div>
</table>
<script>
$(function() {
google.script.run.withSuccessHandler(buildOptionsList)
.getTeamArray();
});
function buildOptionsList(uniqueArray) {
var div = document.getElementById('myList');
for (var i = 0; i < uniqueArray.length; i++) {
var ul = document.createElement('ul');
var li = document.createElement('li');
var cLass = li.setAttribute('class', 'ui-state-default');
var iD = li.setAttribute('id', uniqueArray[i]);
li.appendChild(document.createTextNode(uniqueArray[i]));
div.appendChild(ul);
div.appendChild(li);
}
}
$(function() {
$("#myList, #team1s, #team1a, #team2s, #team2a, #team2s, #team3s, #team3a, #team4s, #team4a").sortable({
connectWith: ".connectedSortable",
update: function(event, ui) {
var changedList = this.id;
var order = $(this).sortable('toArray');
var positions = order.join(';');
console.log({
id: changedList,
positions: positions
});
//Instead of using JSON to save, can I use the spreadsheet itself to save the positions and then pull it from there as I did with "buildOptionsList" above?
function saveList() {
google.script.run.savePositions("myProperty", JSON.stringify(positions));
JSON.parse("myProperty");
}
}
})
});
$(function getPositions(event, ui) {
var changedList = this.id;
var order = $(this).sortable('toArray');
var positions = order.join(';');
console.log({
id: changedList,
positions: positions
});
});
</script>
</body>
</html>
It's also possible to just use the browser's localStorage client side.
localStorage.setItem('id', positions); //Store positions in users browser
localStorage.getItem('id'); //Retrieve the stored positions later
Notes:
For this to work, the url(document.domain of the iframe="*.googleusercontent.com") from which your script is deployed must remain constant. During my brief testing, it was constant even when changing from /dev to /exec of the parent(script.google.com) and even during version update. But there's no official reference.
This solution is better than properties service, if you have multiple users, as each one will have their own data stored in their own browsers and there are no server calls during each change.
Using google.script.run simple example:
<script>
function sendStringToServer() {
var string=$('#text1').val();
google.script.run
.withSuccessHandler(function(s){
alert(s);
})
.saveString(string);
}
</script>
Google Script:
function myFunction() {
PropertiesService.getScriptProperties().setProperty('MyString', string);
return "String was saved in Service";
}
Client to Server Communication

Angular Ui-grid cannot change column displayName

I have ui-grid.
My objects are boxes that may contain boxes or Samples.
Box1 = { 'Name': 'box1', 'Children': [{'Name': 'box2'},{'Name': 'box3'}]}
Box2 = { 'Name': 'box2', 'Children': [], 'Samples [{'Name': '1'}]}
At the beginning I show Box1. User can click Box1 or Box2 and then it opens a link that shows what the box contains.
nameLinkTemplate is link template ("getExternalScopes().followlink)
$scope.gridOptions.columnDefs = ({field: 'Name', displayName: 'Name', cellTemplate: nameLinkTemplate});
If box contains samples I change column to show just name without link.
$scope.gridOptions.columnDefs = ({field: 'Name', displayName: 'Name2', });
As a result I do not see link (that is what I wanted),
but Ui-Grig column headers are not displayed? Why?
I have also tried to reset the Ui-grid by: $scope.gridOptions = []; And define the grid again. Still I cannot change column displayName correctly.
I just added conditions on template and it works:
cellContainerNameLinkTemplate:
<div class="ui-grid-cell-contents" ng-if="row.entity.IsSample" ng-class="col.colIndex()">
<div class="gridnolinkpointer">
{{grid.getCellValue(row, col)}}
</div>
</div>
<div ng-if="!row.entity.IsSample">
<div class="nav nav-pills" ng-class="col.colIndex()" ng-click="getExternalScopes().followlink({event:$event,row:row})">
<a class="gridlinkpointer">{{grid.getCellValue(row, col)}}</a>
</div>
</div>
cell
after you change the name try calling :
$scope.gridApi.core.notifyDataChange(
uiGridConstants.dataChange.COLUMN );
it worked for me

How to get the value of the element selected in ListView JQUERYMOBILE

Hi i'm developping a simple listView that lists the column "firstname" of my table : i want to get the selected value (name) , i found this link but it shows he how to get the index and not the value of the selected item http://jsfiddle.net/w2JZU/
here's my code :
HTML:
<div id="popup-bg">
</div>
<div id="popup-box">
<div data-role="page" id="home">
<div data-role="header">
<h1>Players</h1>
</div>
<div data-role="content">
<ul data-role="listview" id="artiste" >
</ul>
</div>
</div>
</div>
</section>
js :
function successCB()
{
db.transaction(queryDB, errorCB);
}
function queryDB(tx)
{
tx.executeSql('SELECT * FROM Players ', [], querySuccess, errorCB);
}
function querySuccess(tx, results)
{
var len = results.rows.length;
var dataset= results.rows;
$("#artiste").empty();
for (var i = 0; i < len; i++)
{ item = dataset.item(i);
$("#artiste").append( "<li data-theme='c'><a href='game.html'>
<img src='images/avatar.jpg'><h3>"+item['firstName']+"</h3></a></li>" );
}
There isn't a "value" for an item in a list using the li tag. However, you can get the text of what's in that list element using the jQuery .text() method. I've modified the jsfiddle you referenced to do exactly that: http://jsfiddle.net/Cht2e/
You might want to consider adding another attribute to the li tag, such as data-name (you can make up the attribute) and then you can get that via the jQuery .attr() method. For example, you might change you append code to do:
$("#artiste").append( "<li data-theme='c' data-name='"+item['firstName']+"'><a href='game.html'>
<img src='images/avatar.jpg'><h3>"+item['firstName']+"</h3></a></li>" );
And then attach your click handler like this:
$('#artiste').children('li').on('click', function () {
alert('Selected Name=' + $(this).attr('data-name'));
});
I don't think this is necessarily the best structure or approach to take, but it will accomplish what you're asking.

Resources