How do you bind a template containing tds within a tr?
I have a table that I want column sections to be dynamically added/removed/rearranged.
My tds are grouped into categories, the user can pick categories, and then the sections of the table should be pieced together with if/then logic using the category ids.
I'm having trouble binding my category templates into tr. I've tried:
setting the component selector to "app-componentName" and inputting the component using <app-componentName></app-componentName>
setting the component selector to "[app-componentName]" and inputting the component using <template app-componentName></template>
but neither works correctly. Using the first option, all of the data from my category is put into one td. Using the second option, none of my categories show up at all.
Here's the gist...
table-row.component.ts
...
var selectedCategories = [
{
id: 2,
name: "billing address"
},
{
id: 1,
name: "name"
}
];
...
table-row.component.html
<ng-container *ngFor="let category of selectedCategories">
<app-name-cells [person]="person" *ngIf="category.id === 1">
<app-billing-address-cells [person]="person" *ngIf="category.id === 2">
</ng-container>
name-cells.component.html
<td>{{user.firstName}}</td>
<td>{{user.middleName}}</td>
<td>{{user.lastName}}</td>
billing-address-cells.component.html
<td>{{user.billingAddress.line1}}</td>
<td>{{user.billingAddress.line2}}</td>
<td>{{user.billingAddress.city}}</td>
<td>{{user.billingAddress.state}}</td>
<td>{{user.billingAddress.zip}}</td>
Result
//full address in first cell, full name in second cell
|| 123 Main St New York NY 12345 | John A Doe ||
Expected Result
// each part of each component in it's own cell
|| 123 Main St | New York | NY | 12345 | John | A | Doe ||
Edit - Added StackBlitz:
See code example: StackBlitz
Related
So to explain why I need to do that :
I've got a masonry of photos and I need to add an index to each of those photos.
The thing is I can't relie on the index of my v-for because sometimes it is on purpose an "empty case".
|---|---|---|
| | 2 | 3 |
| 1 |---|---|
| | 4 | 5 |
|---|---|---|
| 6 | | 8 |
|---| 7 |---|
| 9 | | 10|
|---|---|---|
The code looks like this.
<div v-for="(row, i) in rphotos" :key="i">
<div v-for="(p, j) in row" :key="i*nbCol+j">
<div v-if="p"
:data-index="index"
class="g-item">
<!-- Increment index there -->
</div>
<div v-else class="g-item g-empty" />
</div>
</div>
However due to vuejs reactivity, my index will always be updated.
An other solution could perhaps be to check through a computed if on the row, g-item is not too a g-empty however I'm not even sure it is possible and yet dont see how precisely I could do this.
My best bet would be to increment a value on display as it is done in PHP template rendering like Smarty or Blade. But since javascript frameworks is meant to be reactive is there a way of doing that ?
Any idea is welcomed.
It's not clear what your data looks like, but you can set an index to each item in rphotos before displaying them so you can then access that index inside the v-for with p.index:
<div v-for="(row, i) in rphotosFiltered">
<div v-for="(p, j) in row">
<div v-if="p.index !== null" :data-index="p.index"></div>
<div v-else/>
</div>
</div>
data(): {
return {
rphotos: [
[
{index: 1, item1: ''},
{index: null, item2: ''}
],
[
{index: 3, item3: ''}
]
]
}
},
computed: {
rphotosFiltered() {
// modify "this.rphotos" list here the way you need it
// return it
}
}
Incrementing a variable during render requires using a method, which breaks reactivity. For this reason, I recommend calculating the index of each image before rendering. In general, the rendering process should be just that--rendering the data that is already there.
If you can't modify the array of image data to include an index property, you could use separate array or hash to store the index values. If the array of image data might be changed by code that is outside your component, you can use a watch to update the index values when the image data changes. In this case also be sure to use the created or mounted hook to initialize the index values when the component is loaded.
UPDATE
Instead of initializing the index values using the created or mounted hook, simply set the immediate property of the watch. This forces it to run when the component is loaded as well as when the watched value changes.
I am pretty new to Angular and I was wondering if there is any way to increment the ngFor loop by 2 instead of 1.
I am trying to implement two pagination's with in a pagination for which increment the loop by 2 is required.
I am getting objects which have objects with in. Lets say users and list of their address.
(First NgFor is to paginate the users by 2. If I get 15 users. 2 users will be displayed in one page)
li *ngFor="let user of Users | paginate: { itemsPerPage: 1, currentPage: p };let i = index"
{{user[i].firstName}} <--Displaying first userName-->
(Second NgFor is to display list of address of the first user. Lets say he has 20 address. I will be slicing it to 3 or 4 per page and paginate the rest)
*ngFor="let address of user[i].address| objectValues |slice:addresspageNumber*2-2:addressPageNumber*5 ; let j = index "
<--First child Pagination code-->
{{user[i+1].firstName}} <--Displaying second userName-->
(Third NgFor is to display list of address of the second user. Lets say he has 20 address. I will be slicing it to 3 or 4 per page and paginate the rest)
*ngFor="let address of user[i+1].address| objectValues |slice:addresspageNumber*2-2:addressPageNumber*5 ; let j = index ">
<th scope="row">{{address.streetno}}
<--Second child Pagination code-->
<--Parent Pagination code-->
Now if I dont increment the first ngFor by two, in the next page the second user will be displayed again which I dont want to.
I either have to increment by 2 or implement pagination seperately for two childs which I cant do it in one for loop
All I want is two separate pagination's to be implemented with in one pagination
Object1.name
object1.address.street
object1.address.pin
-- pagination to display other address.
Object2.name
object2.address.street
object2.address.pin
-- second pagination to display other address.
--main pagination which on click will show two more object details
For increment by 2
<div *ngFor="let item of items; let even = even;">
<div *ngIf="even">
// content
</div>
I don't think you can increment *ngFor by 2 because it's purpose is to display an array-kind data; plus I don't really understand your requirements.
However you can use *ngIf in a combination with % operator in order to not react on every second entry.
This could do the job
<li *ngFor="let item of items; let i = index">
<span *ngIf="i % 2 === 0"> // or <ng-template if it is better here>
The same effect could be achieved for any iteration size. Just replace the 2 with e.g. 10 to increment by 10.
After converting JSON data into a list using jsonlite, i end up with one of the list looking like following
In this case, 10th element contain a list of 9 columns (always fixed) and 2 rows (varies everytime).
mat <- lset$data$comments$data[10]
mat
[[1]]
id can_remove created_time from.id
1 10152663742099258_10152663749369258 TRUE 2014-07-01T11:10:29+0000 10203711779968366
2 10152663742099258_10152663842204258 TRUE 2014-07-01T12:15:57+0000 706804257
3 10152663742099258_10152663929639258 TRUE 2014-07-01T13:25:28+0000 10152738599744416
4 10152663742099258_10152663976344258 TRUE 2014-07-01T13:59:33+0000 706804257
from.name like_count
1 Aileen Yeow 1
2 Tejas Damania 0
3 Sandeep Kulkarni 1
4 Tejas Damania 0
message
1 Lame statement
2 Don't forget, people like you only because they don't know you! <ed><U+00A0><U+00BD><ed><U+00B8><U+00A1>
3 ...for a second I thought it's Accenture Singapore office with some new theme similar to its brand!
4 This is shanghai and nothing to do with firm I work for <ed><U+00A0><U+00BD><ed><U+00B8><U+008E>
user_likes
1 FALSE
2 FALSE
3 TRUE
4 FALSE
Whole mat shows us as a list of [1]
As you can see, it contains list (within a list?). When i print mat then it shows a structure as seen above.
typeof(mat)
[1] "list"
substring(mat,1,100)
[1] "list(id = c(\"10152663742099258_10152663749369258\", \"10152663742099258_10152663842204258\", \"101526637"
I cant access specific elements (say message) from this. Nor I am able to convert this into a matrix of strings so I can access the elements in structured way.
I changed the fromJSON call parameter to by setting simplifyVector = FALSE (which is default set to true)
lset <- fromJSON(jsonobj, simplifyVector = F, flatten=TRUE, unicode = TRUE)
this changes the way mat is formed, code maintain nesting all the way down to each leaf element. I can keep going deeper using $ and find the string value only at leaf element!
lset$data[[x]]$comments$data[[y]]$from$name
That works for now! thanks for all the help
I'm trying to define an element for an automated test using ruby + selenium.
The element has 3 attributes I'm trying to combine. 1st, a parent div, 2nd, an ID, and 3rd, a name. The Id and name I must combine to create a unique ID that the element should be able to be called by.
So...
Element = (ID + Name) + parent div
Here is an example of the element:
This element id of "730_Test%Profile" is created when a new entry is created on the table on the page I'm automating. The ID# of 730 is one variable on the table in the page and "Test Profile" is another variable on the table on the page. They get combined together to create the element mentioned above. In attempting to define this element in ruby:
element(:edit) { | edit_name | browser.div(id:edit_name).parent.div(class:'editHolder') }
element(:id_value) { |id| browser.div(id:id)}
Where "edit_link" is just the name part (pointer set up to give "edit_link" value of name)
"id_value" is the ID part (pointer set up to give "id_value" value of the id)
I need to combine to create the element mentioned above. I cant call the element by its direct name because the full name "730_Test%Profile" is created while the automated test is running...so I have to piece it together while the test is running using the pointers from two different variables (Integer and String) to create the unique ID for this element. So far, these lines of code are not identifying the element correctly:
element(:edit_name) { | edit_name | browser.div(id:edit_name) }
element(:id_value) { |id| browser.div(id:id)}
element(:selection){browser.div(id:'#id + "_" + edit_name').parent.div(class:'editHolder')}
(element "selection" is the focus)
Perhaps you want to do:
element(:selection) { |id_value, edit_name| browser.div(id: "#{id_value}_#{edit_name.gsub(' ', '%20')}") }
This is creating a selection method that finds a div by id using the known/provided id and name.
The method would be called like:
id_value = 730
edit_name = 'Test Profile'
#site.your_page.selection(id_value, edit_name)
Suppose your dataset is
Street
Housenumber
InhabitantNumber
InhabitantDataType
InhabitantDataValue
So you might have
Monkeystreet : 23 : 1 : Name : Bob Smith
Monkeystreet : 23 : 1 : DOB : 01.01.1950
Monkeystreet : 23 : 2 : Name : Sheila Smith
Monkeystreet : 23 : 2 : MaritalStatus: Married
Monkeystreet : 27 : 1 : Name : John Doe
Goatroad : 15 : 1 : Name : Sally Mither
Goatroad : 15 : 1 : DOB : 02.02.1970
Note: There can be varying amounts of data per inhabitant
Now I pivot this data
So the columns are
Street : HouseNumber : Inhabitant : InhabitantData
MonkeySt. : 23 : 1 : Name: BobSmith
DOB : 01.01.1950
: 2 : Name: SheilaSmith
MarSt: Married
: 27 : 1 : Name: John Doe
-------------------------------------------------------------
Goatroad : 15 : 1 : Name: Sally Mither
: DOB : 02.02.1970
So I have a row grouping on 'streetname' and one on 'housenumber' and the 'inhabitant data' is in a table detail group
How can I make this inhabitant data 'show' or 'hide' with a toggle?
You actually need a third grouping to make the toggle work. If you group by the InhabitantNumber and then add a toggle to that grouping you will be able to show and hide the InhabitantData.
I used a test query to create the mock data you attached to your post and actually used the report wizard to create this exact behavior. Here are the steps you can take if you have your query written to create it via the Report Wizard in BIDS:
Right-Click Reports folder
Click Add New Report -> Click Next button
Setup Data source or reuse existing shared one -> Click Next button
Paste query into Query string: text area or use Query builder -> Click Next button
Choose Tabular Report Type -> Click Next button
Put the following into the Group text area using the Group> button
Street
Housenumber
InhabitantNumber
Please Note: The order you put the columns into this box determines the hierarchy of the groupings
Put the following into the Details text area using the Details> button
InhabitantDataType
InhabitantDataValue
Click Next button
Choose Stepped and click Enable drilldown checkbox -> Click Next button
Choose the Table style you prefer -> Click Next button
Name your report -> Click Finish button
This is the easiest way to create the stair stepped / toggle per grouping report. You could create it manually but just be sure to add that third grouping (by InhabitantNumber) and enable the toggle.
-Paul