angular component DOM add attribute key - angularjs

I'am looping on DOM element of angular component with ngfor like that
<td>
<button class="dropdown-item" idgroup={{compte_ingroup}} href="#">
action
</button>
</td>
my question is about to know how to add reference to element create in loop.
this issue happen to me ==> Can't bind to 'idgroup' since it isn't a known property of 'button'
please what I'am doing wrong?

If what you have is a component which template is
<td>
...
</td>
you should provide a property to it called idgroup, and when you invoke that component should be something like this:
<app-mycomponent *ngFor="let myelement of elementsList" [idgroup]="myelement.idgroup"></app-movie>
and in the component definition:
#Component({
...
})
export class MyComponent {
#Input() idgroup: any;
...
}

Related

How to call a method when a select box is initialized in an Angular app

I have used a select box inside a row. The row is generated using a loop. I need to call a method when this select box is
initialized. This method will pass the dynamically generated row data as an argument.
I am confused as to how this can be achieved in Angular4/5.
In AngularJS it could be done like this:
<tr ng-repeat="row in myData track by $index">
<select class="form-control" ng-model="row.val" ng-init="methodToCall(row)">
</tr>
I might use my own component for that purpose:
So create new component as follow:
import {Component, onInit, Input} from "#angular/core";
#Component({
selector: "custom-select"
})
export class customeSelect implements onInit{
#Input() row:any;
ngOnInit(){
//You can call what ever you want after your component initialized.
console.log(this.row);
}
}
and use it in your ngfor like below:
<tr *ngFor="row in myData">
<custom-select [row]="row"></custom-select>
</tr>

Array object received from service but cannot iterate through it?

I have got a recipe web app, and i have a 'add recipe' page with a child component 'add ingredient' nested and called within its HTML as seen here:
<h2>Add {{addRecipeForm.controls.name.value}}</h2>
<form [formGroup]="addRecipeForm">
...
<app-add-ingredient></app-add-ingredient>
<hr>
<button type="submit">Add new recipe</button> <button (click)="goBack()">Back</button> <button (click)="test()">check if array was caught</button>
</form>
<p>Recipe ingredient list (from service)</p>
<div *ngIf="ingredientList">
<table>
<tr>
<th>ID</th>
<th>Name</th>
<th>Quantity</th>
<th>Units and Style</th>
</tr>
<tr *ngFor="let ingre of ingredientList">
<td>{{ingre.ID}}</td>
<td>{{ingre.name}}</td>
<td>{{ingre.quantity}}</td>
<td>{{ingre.unitsAndStyle}}</td>
</tr>
</table>
</div>
I then added a button to ensure the data sent from the service was actually received in correct format etc (as seen in the screenshot I got it sends the object perfectly when the child component adds the ingredient) but when I try and present it with the table as shown I get this error:
Cannot find a differ supporting object '[object Object]' of type
'fawf'. NgFor only supports binding to Iterables such as Arrays.
I know the service isnt the problem because my 'test()' function just logs the array and its all there as seen in the screenshot.
https://github.com/angular/angular/issues/6392
This seems to list a similar issue and they resolved it by making a small 'hack' to overcome that error.
hack(val) {
return Array.from(val);
}
A workaround found here Iterate over object in Angular
import { Pipe, PipeTransform } from '#angular/core';
#Pipe({ name: 'values', pure: false })
export class ValuesPipe implements PipeTransform {
transform(value: any, args: any[] = null): any {
return Object.keys(value).map(key => value[key]);
}
}
did the trick

why row is not render in angular 2?

I am trying to send data from one component to another using input attr.
but I am getting this error
VM575 zone.js#0.6.17?main=browser:484 Unhandled Promise rejection: Template parse errors:
Can't bind to 't' since it isn't a known property of 'row-item'.
1. If 'row-item' is an Angular component and it has 't' input, then verify that it is part of this module.
2. If 'row-item' is a Web Component then add "CUSTOM_ELEMENTS_SCHEMA" to the '#NgModule.schema' of this component to suppress this message.
(" <ul>
<li *ngFor="let tt of todoService.todos">
<row-item [ERROR ->][t]='tt'></row-item>
</li>
I added this in my demo
import {Component, Input} from "#angular/core";
#Component({
selector:'row-item',
template :`<div>
<span>{{t}}</span>
</div>`
})
export class TodoRow{
#Input t;
}
used like this
#Component({
selector: 'todo-list',
template: `<div>
<ul>
<li *ngFor="let tt of todoService.todos">
<row-item [t]='tt'></row-item>
</li>
</ul>
</div>`
})
here is my code
http://plnkr.co/edit/WXgdKF2gx9Kpj7eqmDJv?p=preview
Your declaration should be something like this:
#Input() t;
You forgot to add () while defining you input for the component.
import {Input} from '#angular/core';
Input() t;
You should try providing base name while providing input for the component:
#Input('t') t;
Hope this helps.

react ref with focus() doesn't work without setTimeout (my example)

I have encounter this problem, the .focus() only works with setTimeout if i take it out and it stop working. can anyone explain me what's the reason for that, possible i am doing it incorrectly and how can i fix the problem.
componentDidMount() {
React.findDOMNode(this.refs.titleInput).getElementsByTagName('input')[0].focus();
}
works example with setTimeout
componentDidMount() {
setTimeout(() => {
React.findDOMNode(this.refs.titleInput).getElementsByTagName('input')[0].focus();
}, 1);
}
JXS
<input ref="titleInput" type="text" />
and i have followed this example React set focus on input after render
render function
render() {
const {title, description, tagtext, siteName} = (this.state.selected !== undefined) ? this.state.selected : {};
const hasContentChangedYet = this.hasContentChangedYet(title, description);
return (
<div>
<h2 className={styles.formMainHeader}>Edit Meta-Data Form</h2>
<table className={styles.formBlock}>
<tbody>
<tr>
<td className={styles.tagEditLabel}>
Tag
</td>
<td className={styles.inputFieldDisableContainer}>
{tagtext}
</td>
</tr>
<tr>
<td className={styles.tagEditLabel}>
Site
</td>
<td className={styles.inputFieldDisableContainer}>
{siteName}
</td>
</tr>
<tr>
<td className={styles.tagEditLabel}>
Title
</td>
<td className={styles.inputFieldContainer}>
<ReactInputField
ref="titleInput"
id="title"
defaultValue={(title) ? title : ''}
onChange={this.onInputChange}
placeholder="Title"
clearTool={true} />
</td>
</tr>
<tr>
<td className={styles.tagEditLabel}>
Description
</td>
<td className={styles.inputFieldContainer}>
<ReactInputField
id="description"
defaultValue={(description) ? description : ''}
onChange={this.onInputChange}
placeholder="Description"
clearTool={true} />
</td>
</tr>
</tbody>
</table>
<div className={styles.formFooter}>
<button id="save-button" className={styles.saveButton} disabled={!hasContentChangedYet} onClick={() => this.handleSavePressed()}>
Save
</button>
<button id="form-cancel-button" className={styles.cancelButton} onClick={this.actions.form.cancelUpdateToTagData}>
Cancel
</button>
</div>
</div>
);
}
After seeing the update to the question, I realise that you have deeply nested HTML passed to the render function, and the input element of your interest will indeed not be available at the time of the componentDidMount call on the ancestor element. As stated in the React v0.13 Change Log:
ref resolution order has changed slightly such that a ref to a component is available immediately after its componentDidMount method is called; this change should be observable only if your component calls a parent component's callback within your componentDidMount, which is an anti-pattern and should be avoided regardless
This is your case. So either you have to break down the HTML structure into separately rendered elements, as described here, and then you would access the input element in its own componentDidMount callback; or you just stick with the timer hack you have.
Use of componentDidMount makes sure the code runs only when the component on which it is called is mounted (see quote from docs further down).
Note that calling React.findDOMNode is discouraged:
In most cases, you can attach a ref to the DOM node and avoid using findDOMNode at all.
Note
findDOMNode() is an escape hatch used to access the underlying DOM node. In most cases, use of this escape hatch is discouraged because it pierces the component abstraction.
findDOMNode() only works on mounted components (that is, components that have been placed in the DOM). If you try to call this on a component that has not been mounted yet (like calling findDOMNode() in render() on a component that has yet to be created) an exception will be thrown.
And from the docs on the ref string attribute:
Assign a ref attribute to anything returned from render such as:
<input ref="myInput" />
In some other code (typically event handler code), access the backing instance via this.refs as in:
var input = this.refs.myInput;
var inputValue = input.value;
var inputRect = input.getBoundingClientRect();
Alternatively, you could eliminate the need of the code, and use the JSX autoFocus attribute:
<ReactInputField
ref="titleInput"
autoFocus
... />
Using setTimeout() is a bad idea and using componentDidMount() is irrelevant. You may find the answer to your question in the following example:
In a parent component I render a primereact Dialog with an InputText in it:
<Dialog visible={this.state.visible} ...>
<InputText ref={(nameInp) => {this.nameInp = nameInp}} .../>
...
</Dialog>
Initially, this.state.visible is false and the Dialog is hidden.
To show the Dialog, I re-render the parent component by calling showDlg(), where nameInp is the ref to InputText:
showDlg() {
this.setState({visible:true}, ()=>{
this.nameInp.element.focus();
});
}
The input element gets the focus only after rendering has been accomplished and the setState callback function called.
Instead of using the setState callback, in some cases you may simply use:
componentDidUpdate(){
this.nameInp.element.focus();
}
However, componentDidUpdate() is being called every time you (re)render the component, including in case the InputText is hidden.
See also: https://reactjs.org/docs/react-component.html#setstate

Underscore.js templates in backbone.js adding a div around a tr

I am using underscore.js's templating capabilities from backbone.js, I have the following template that I define in my page like this:
<script type="text/template" id="businessunit_template">
<tr data-uid="{{Uid}}">
<td class="first"><span>{{Name}}</span></td>
<td class="{{StatusClass}} tac">{{OverallScore}}%</td>
<td>
<a class="impactanalysis individualBu" href="#"> </a>
</td>
</tr>
</script>
I am attaching the trs to the tbody element of following table:
<table class="listing">
<thead>
<tr>
<th class="first">Business Units</th>
<th>BCMS<br />Status</th>
<th>View</th>
</tr>
</thead>
<tbody id="reportBusinessUnits"></tbody>
</table>
My individual backbone view that renders the tr looks like this:
class ReportBusinessUnitView extends MIBaseView
initialize: (options) ->
#vent = options.vent
#template = _.template($('#businessunit_template').html())
events:
"click .individualBu": "showBusinessUnitDetail"
showBusinessUnitDetail: (e) =>
e.preventDefault()
self = #
#vent.trigger('management:showbusinessunitdeail', #model)
render: =>
$(#el).html(#template(#model.toJSON()))
#
The problem is, the rendered output has a div around the tr and I have no idea where it is coming from:
<div>
<tr data-uid="a5e3c218-1ca4-4806-b27e-24a25ed83ab6">
<td class="first"><span>Central Networks</span></td>
<td class="red tac">4%</td>
<td>
<a class="impactanalysis individualBu" href="#"> </a>
</td>
</tr>
</div>
I just cannot see what I am doing wrong. Has anybody any idea where this could be coming from?
That looks very much like the kind of faulty DOM fragment you get when you haven't declared the .el attribute in a View correctly. I'd put a breakpoint/debugger statement in ReportBusinessUnitView.render() and inspect the value of the this.el attribute from there. (View.el docs).
Also, check your code:
Have you declared an .el property? (in MIBaseView for example)
Does it hit the right DOM node?
If not, Backbone auto creates the DIV node for you, which can be confusing.
The inclusion of a default DIV tag to surround the template is, I believe, a safety measure. This gives a parent tag to which the view's events are attached. That way event propagation will work as expected. As well, if you discard a view and remove the inserted HTML all events will go with it allowing the garbage collector to do its job.
I recently had considerable grief because I set the .el to the static HTML parent node (in order to prevent the default DIV from being added). Since it remained even after my dynamic HTML was replaced the events were still around responding to actions and creating general chaos!

Resources