43

I am trying to print json object in textarea using ngModel.

I have done following:

<textarea style="background-color:black;color:white;" [(ngModel)]='rapidPage' rows="30" cols="120">                             
</textarea>

I want to load the json object in textarea. The above code is loading the rapidPage object in textarea but its showing textarea value as [object Object].

object:

 this.rapidPage = {            
        "pageRows": [
            {
                "sections": [
                    {
                        "sectionRows": [
                            {
                                "secRowColumns": [                                       
                                ]
                            },
                            {
                                "secRowColumns": [
                                    {
                                        "colName": "users"
                                    }
                                ]
                            },
                            {
                                "secRowColumns": [
                                    {
                                        "colName": "sample"
                                    }
                                ]
                            }
                        ],
                        "width": 0
                    }
                ]
            }
        ],
        "pageName": "DefaultPage",
        "pageLayout": "DEFAULT_LAYOUT",
        "editMode": true
    };

I want to load the data as string. any inputs?

Ankit Singh
  • 24,525
  • 11
  • 66
  • 89
Bhushan Gadekar
  • 13,485
  • 21
  • 82
  • 131

9 Answers9

37

Assuming that you want to bind rapidPage as it is and will only write valid JSON in the textArea.

  • You need to PARSE it when changing the value, and STRINGIFY when showing in textarea.

StackBlitz DEMO

Do the following in your Component code

  rapidPage = {"pageRows":[{"sections":[{"sectionRows":[{"secRowColumns":[]},{"secRowColumns":[{"colName":"users"}]},{"secRowColumns":[{"colName":"sample"}]}],"width":0}]}],"pageName":"DefaultPage","pageLayout":"DEFAULT_LAYOUT","editMode":true}; 
  // your object

  get rapidPageValue () {
    return JSON.stringify(this.rapidPage, null, 2);
  }

  set rapidPageValue (v) {
    try{
    this.rapidPage = JSON.parse(v);}
    catch(e) {
      console.log('error occored while you were typing the JSON');
    };
  }

Template Usage:

<textarea [(ngModel)]='rapidPageValue' rows="30" cols="120">                             
</textarea>
Ankit Singh
  • 24,525
  • 11
  • 66
  • 89
  • i got the output correctly.thanks.is there any way to indent this json object because series of characters is too mainstream. – Bhushan Gadekar May 20 '16 at 12:59
  • you'll have to use a code beutifier plugin of some short to achieve that, I haven't done anything like this before, there might be some `api`s too that might provide you with formatted json on just one api call. – Ankit Singh May 20 '16 at 13:02
  • beautification is possible with JSON.stringify as well, I updated my answer and plunker. see [this question](http://stackoverflow.com/questions/2614862/how-can-i-beautify-json-programmatically) too. – Ankit Singh May 20 '16 at 13:08
  • 1
    Already did that. :) I am novice in angular2,if possible can you share any details of your social profile.would like to learn from you. :) – Bhushan Gadekar May 20 '16 at 13:08
  • 1
    Unrealistically true, I am not active on any social network anymore, But I visit stackoverflow everyday. You can just post your questions and I'll try my best. you can find my mail on SO profile. Thanks for your kind consideration, but SO has much more talented and active people than me. – Ankit Singh May 20 '16 at 13:12
20
<textarea class="form-control" 
          name="message"
          rows="8"
          [(ngModel)]="Obj.message"
          #message='ngModel'
          ></textarea>

for Two way binding You just need to add attribute in textarea tag name="message", ONLY [(ngModel)] works 100%!.

  • 3
    Great answer. A bit strange, but apparently the `[(ngModel)]` thing doesn't work without a `name` attribute. - Having said that, I found the `#message='ngModel'` in your answer a bit confusing, as this seems unnecessary and seems to make no difference. – bvdb Feb 23 '19 at 21:16
  • 2
    my text area [formControl] binding didn't work until I added name attribute. thanks! – ihor.eth Oct 21 '19 at 15:50
  • 1
    I agree with @ihorbond. Same for me. – Sharmila Jun 05 '20 at 09:38
  • 1
    Not working on Angular 9, here is my error message : `Cannot assign value "$event" to template variable "message". Template variables are read-only.` – jpmottin Jul 08 '20 at 05:07
14

For binding textarea values in Angular 2 you can use the change-function:

Template

<textarea id="some-value" (change)="doTextareaValueChange($event)">{{textareaValue}}</textarea>

Component

export class AppComponent implements OnInit {
  private textareaValue = '';
  doTextareaValueChange(ev) {
    try {
      this.textareaValue = ev.target.value;
    } catch(e) {
      console.info('could not set textarea-value');
    }
  }
}
Markus Brunner
  • 179
  • 1
  • 2
7

ngModel works if

  1. There is a form wrapped around it & textarea has a name attribute added to it.

If you not you can use the following syntax to achieve the same effect

<textarea [value]="strVariableInComponent" (input)="strVariableInComponent = $event.target.value;"></textarea>
Anand Rockzz
  • 6,072
  • 5
  • 64
  • 71
5

Unless you really want to have sync in between, you would normally implement a button to save/apply the change when it's finished json editing. If that is the case, your render is easy.

<textarea #textbox>{{ rapidPage | json }}</textarea>

Make sure no other space or return character in between the above line.

Then an traditional button, ex.

<a (click)="updateRapidPage(textbox.value)">Apply</a>

I found this is better in some case than brutal [(rapidPage)].

You can also use @ViewChild('textbox') input inside the component to access this variable.

windmaomao
  • 7,120
  • 2
  • 32
  • 36
2

Can you test with this:

<textarea #textbox (change)="text = textbox.value" style="width:100%;">{{ text }}</textarea>

Regards

  • An explanation as to why this code works or what changes you had to make and why would be helpful to the person who originally asked the question. – Scotty Waggoner Jul 26 '18 at 21:36
  • Should have added a fiddle with your code. This is not even an answer. – retr0 May 28 '21 at 09:23
1

As per documentation [()] is for two way syntax sugar to remove the boilerplate. What event is being invoked at this? Irrespective, you can put a string output also alongwith the event in below code

Probably try the below code implemetation for your string output

@Directive({
  selector: '[ngModel]',
  host: {
    "[value]": 'ngModel',
    "(input)": "ngModelChange.next($event.target.value)"
  }
})
class NgModelDirective {
  @Input() ngModel:any; // stored value
  @Output() ngModelChange:EventEmitter; = new EventEmitter() // an event emitter
}
mattyman
  • 351
  • 2
  • 16
0

You can stringify your json and use in the ngModel like this -

<textarea style="height:100px; width:300px;background-color:black;color:white;" [(ngModel)]='rapidPage' rows="30" cols="120">
    </textarea>

ArrayDemo: Array<any> = [{"name":"pardeep","last":"jain"}]
  rapidPage = JSON.stringify(this.ArrayDemo);

Working Example Working Example

Browser shows [object object] because angular unables to parse the JSON the asign the value in ngModel you must need a string so convert this using JSON.stringify

Pardeep Jain
  • 84,110
  • 37
  • 165
  • 215
0

I find that importing FormsModule from @angular/forms solves the issue.

In app.module.ts

import { FormsModule } from '@angular/forms';

@NgModule({
  declarations: [
    AppComponent
  ],
  imports: [
    ...
    FormsModule
  ],
...
})