4

I have a simple form input component in my angular2 app which contains an @Input binding to the attribute [dataProperty]. As you may have guessed, the [dataProperty] attribute is a string value of the format: [dataProperty]="modelObject.childObj.prop", where the modelObject is the model shared throughout my application. Basically, I'm using this @Input attribute to pass the model from a parent component to my <custom-text-input> component, where it is then bound by [ngModel] to the nested component's input.

Everything works as intended and in my controller; i.e. when I access this.dataProperty the value on the model to which the input binds is returned. What I can't seem to find out, however, is how to access the string literal passed to [dataProperty] from the template in the first place.

Component:

@Component{
    selector: "custom-text-input",
    template: "<input type="text" [ngModel]="dataProperty"></input>
}

export Class customInputComponent implements OnInit {
    @Input() dataProperty: string;

    /**
       ex of modelObject: { detail: { name: "Cornelius" } }
       (^^^ would originate in parent component ^^^)
    */

    constructor() {}

}

Use Case:

<div class=wrapper>
    <custom-text-input [dataProperty]="modelObject.detail.name">
    </custom-text-input>
</div>

Basically, when I go to access this.DataProperty from the component controller it returns "Cornelius". Is it possible to access the string literal so that I can capture the "modelObject.detail.name" string from my controller as well?

john_mc
  • 1,333
  • 11
  • 16

4 Answers4

3

I would create a key-value pair of the property and it's name and pass them in together like so:

<div class="wrapper">
    <custom-text-input [dataProperty]="{modelObject.detail.name}">
    </custom-text-input>
</div>

Then I would gain access to the property name by doing something like this:

@Component{
    selector: "custom-text-input",
    template: "<input type="text" [ngModel]="dataProperty"></input>
}
export Class customInputComponent {

    dataPropertyName;

    private _dataProperty;    
    @Input() 
    set dataProperty( keyValuePair ){
      this._dataProperty = Object.values(keyValuePair)[0]
      this.dataPropertyName = Object.keys(keyValuePair)[0]
    }
    get dataProperty( ){
      console.log( "I have the property name here:" + this.dataPropertyName )
      return this._dataProperty
    }

}

Hope this helps!

Somo S.
  • 3,997
  • 4
  • 26
  • 33
0

Technically, this should be possible. But you have to think somewhat out of the box. The element with the dataProperty is, in the end, just a HTML node.

<custom-text-input [dataProperty]="modelObject.detail.name">

I'm not in a position at the moment to create an example for you, but you could simple get a reference to the components HTML (using Angular viewReference in your component) and simply query the attribute on it. Pseudo code would something like

 let myString = viewref.nativeElement.getAttribute('[dataProperty]')

Again, I haven't tested it, but I see no reason why this wouldn't work.

MikeOne
  • 4,789
  • 2
  • 26
  • 23
  • This unfortunately would not work, as the rendering converts the object into `[object Object]` – Mezo Istvan Jan 27 '17 at 20:23
  • Did you try it? – MikeOne Jan 27 '17 at 20:24
  • yes. heres a plunker: https://plnkr.co/edit/uJH17jhWxeJlfMjxUPoj but this does not even keep the input property in the DOM. I've seen it rendered multiple times as [object Object] though – Mezo Istvan Jan 27 '17 at 20:39
  • 1
    Angular strips away all of your bound properties during compile time. You wouldn't even see [object Object] if you ran it in production mode. – smoyer Jan 27 '17 at 21:05
  • Neh you're right. The original nodes from the template will only be added after compilation, than the original attribute is gone... Too bad.. Let's think some more :-) – MikeOne Jan 27 '17 at 21:22
0

Unfortunately, angular 2 uses the default conversion from Object to string, in this case, and will only display the familiar [object Object] in the DOM. You cannot get more information out of that.

Also, the object does not know anything about its parent object. See: Access parent's parent from javascript object

You could use something like Somo's answer: provide the value as a property of an object. The name of the property should be the string literal, the value of the property should be the actual value.

Use Case:

<div class="wrapper">
    <custom-text-input [dataProperty]="{'modelObject.detail.name': modelObject.detail.name}">
    </custom-text-input>
</div>

Component:

@Component{
    selector: "custom-text-input",
    template: "<input type="text" [ngModel]="actualValue"></input>
}

export Class customInputComponent implements OnInit {
    @Input() dataProperty: Object;
    actualValue: string;

    ngOnInit() { 
        console.log( Object.keys( dataProperty )[0] );
        console.log( Object.values( dataProperty )[0] );
        this.actualValue = Object.values( dataProperty )[0];
    ) }    
}
Community
  • 1
  • 1
Mezo Istvan
  • 2,664
  • 1
  • 14
  • 17
-1

Edit

So it looks like the question is about printing the name of the variable instead of the value. That's not possible.

You can access the value from the controller:

export Class customInputComponent implements OnInit {
    @Input() dataProperty: string; 

    constructor() {
       console.log(this.dataProperty) // would print modelObject.childObj.prop
    }

}

If your asking about Interpolation, you do this:

{{dataProperty}} <input type="text" [ngModel]="dataProperty"></input>

More info:

https://angular.io/docs/ts/latest/guide/template-syntax.html

Sumama Waheed
  • 3,579
  • 3
  • 18
  • 32
  • It's not interpolation I'm looking for. I'm trying to access the string value passed to the input attribute from my controller for use with one of my services. – john_mc Jan 27 '17 at 19:09
  • 1
    you've already done that haven't you using "this.DataProperty" in your child component. If you console log "this.DataProperty", it would print the value – Sumama Waheed Jan 27 '17 at 19:10
  • I don't want the value since I already have it. I want the string literal i.e. "modelObject.detail.name". Also, interpolation isn't necessary because the ngModel directive already binds the model value to the text in the input – john_mc Jan 27 '17 at 19:12
  • Not sure this is what John is asking for. He's asking how to get the *name* of the value being passed in, not the value. – Charlie Jan 27 '17 at 19:13
  • You can't make the child component literary print "modelObject.detail.name", what good would that do – Sumama Waheed Jan 27 '17 at 19:13
  • Hrmm... sounds he may be trying to track changes in various models. Have a list of what changed, tracked by name? – Charlie Jan 27 '17 at 19:15