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
Related
I'm trying to create web templates using React.js, and have an array where I list different content fragments (based on which page is rendered). I'm struggling to understand how to use a combination of filter and map in order to extract the relevant parts of the array.
At the moment, I'm trying to use the id (although being able to use the pathname would be ideal) and have the following:
// My Array
const Top = [
{
id: 1,
path: "/myfirstpath",
title: "My First Title",
content1: "Some first content",
content2: "some more first content",
},
{
id: 2,
path: "/mysecondpath",
title: "My Second Title",
content1: "Some second content",
content2: "Some more second content",
}
]
export default Top;
What I'd like to be able to do is pull out everything that's in the id: 1 object, and render it in this framework:
// My Content Framework
import React from "react";
function Content(props) {
return (
<div className= "container-top">
<section class="header">
<div class="wrapper">
<div class="title">
<h1>{props.title}</h1>
</div>
<div className="description">
<p>{props.content1}</p>
<p>{props.content2}</p>
</div>
</div>
</section>
</div>
)
}
export default Content;
Then, for another page, I'd like to do the same for id: 2, and so on.
And here's where I've got to so far:
// My Attempt to Populate My Content
function createContent(selectedObject) {
return (
<Content
key={selectedObject.id}
title={selectedObject.title}
content1={selectedObject.content1}
content2={selectedObject.content2}
/>
);
}
function renderedContent() {
return(
<div>{TopBox.filter("What goes in here?!")}</div>
)
}
export default renderedContent;
I've tried the following where I've written "What goes in here?!":
(selectedObject => selectedObject.id === "1").map(createContent)
(createContent => createContent.id === "1").map(createContent)
Apologies if the terminology I've used isn't correct - I'm quite new to all this!
Thanks for any advice you can lend.
You were actually quite close. You can use Array.filter(f => condition) to filter based on whatever property you need.
The filter() method creates a new array with all elements that pass the test implemented by the provided function.
const words = ['spray', 'limit', 'elite', 'exuberant', 'destruction', 'present'];
const result = words.filter(word => word.length > 6);
console.log(result);
// expected output: Array ["exuberant", "destruction", "present"]
Where you probably went wrong was in (selectedObject => selectedObject.id === "1").map(createContent). In JavaScript 1 === '1' is false. Strict equality compares two values for equality. If the values have different types, the values are considered unequal.
In the example below, I use content.id === 1 as the filter condition (as per your question), and it displays the Content with id=1.
function Content(props) {
return (
<div className="container-top">
<section class="header">
<div class="wrapper">
<div class="title">
<h1>{props.title}</h1>
</div>
<div className="description">
<p>{props.content1}</p>
<p>{props.content2}</p>
</div>
</div>
</section>
</div>
);
}
function createContent(selectedObject) {
return (
<Content
key={selectedObject.id}
title={selectedObject.title}
content1={selectedObject.content1}
content2={selectedObject.content2}
/>
);
}
function App() {
const Top = [
{
id: 1,
path: '/myfirstpath',
title: 'My First Title',
content1: 'Some first content',
content2: 'some more first content'
},
{
id: 2,
path: '/mysecondpath',
title: 'My Second Title',
content1: 'Some second content',
content2: 'Some more second content'
}
];
const filterBy = (content) => content.id === 1; // <= use whatever prop/value
return <div>{Top.filter(filterBy).map(createContent)}</div>;
}
ReactDOM.render(<App />, document.getElementById("react"));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/17.0.1/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.1/umd/react-dom.production.min.js"></script>
<div id="react"></div>
You can swap the id for pathname as well in the filterBy method.
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);
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
I am creating a fairly simple stats page for a dashboard in my rails application. I am using react-rails to create react components in my app and have one for a stat card.
For these cards I have created a very simple react component
import React from "react";
import PropTypes from "prop-types";
class StatCard extends React.Component {
render() {
const { title, data } = this.props;
return (
<React.Fragment>
<div className="card">
<div className="card-body">
<div className="row align-items-center">
<div className="col">
<h6 className="card-title text-uppercase text-muted mb-2">
{title}
</h6>
<span className="h2 mb-0">{data}</span>
</div>
<div className="col-auto">
<span className="h2 fe fe-briefcase text-muted mb-0" />
</div>
</div>
</div>
</div>
</React.Fragment>
);
}
}
StatCard.propTypes = {
title: PropTypes.string,
data: PropTypes.integer
};
export default StatCard;
In my html page right now I have 4 different components listed by calling this 4 different types with different data and a different title.
<%= react_component("StatCard", {title: 'Total users', data: #users.count }) %>
Would the best practice be to list an array of objects with this data listed and iterate over that and generate those components that way? If so, would this be data be best in the model or the controller?
The data structure might look something like this.
data = [
{ title: 'Total users', data: #users.count },
{ title: 'Total questions', data: #questions.count }
]
It is a good practice to have array of objects and iterate through that to return multiple similar components. you are using instance of user to get the count so it would be fine if you have them in controller
trying to do the boolean "Binding element attributes" thing from the Guide.
The javascript is:
window.App = Ember.Application.create();
window.App.NumberTextField = Ember.TextField.extend({
valueChanged: (function() {
return this.get("controller").set("isNotCompleteId", this.get("value").length !== 6);
}).observes("value")
});
window.App.LandingController = Ember.ObjectController.extend({
isNotCompleteId: true
});
window.App.Router.map(function() {
return this.route("landing", {
path: "/"
});
});
The template is:
<h3>Example:</h3>
<script type="text/x-handlebars">
<p>
<a href="#"
{{bindAttr disabled="isNotCompleteId"}}>
Join number:
</a>
{{view App.NumberTextField valueBinding="idEntered" size="8"}}
<p>{{idEntered}}</p>
</p>
</script>
This jsfiddle shows (what I think is the) bad behavior: http://jsfiddle.net/csterritt/AaTpd/11/
Inspect the "Join number:" link in the Result pane. It doesn't have the "disabled" attribute (I believe it should). Changing the text in the text box until it has six characters doesn't change the attribute (it should, at six chars).
If I change line 7 of the HTML to {{bindAttr class="isNotCompleteId:foo:bar"}} it works as expected (although the class starts as "bar", and so, the controller attribute starts as false even though I set it to true...???).
Bug? Confusion on my part?
Thanks!