1

I am trying to implement a Component which corresponds to a Bootstrap modal including an input. The input is hooked to a variable in the Component class via [(ngModel)]="..." This works if I enter text inside the input (the variable's value gets updated).

What I want to do is that when this component's show() method gets called the input should be populated with text passed in as a parameter. This does not seem to work and I can't figure out how I can set the initial text passed in as a parameter (without using jQuery).

Here's the relevant code:

editdialog.component.html

<div id="edit_todo_modal" class="modal">
  <div class="modal-dialog" role="document">
    <div class="modal-content">
      <div class="modal-header">
        <h5 class="modal-title">Edit todo</h5>
        <button type="button" class="close" data-dismiss="modal" aria-label="Close">
                <span aria-hidden="true">&times;</span>
              </button>
      </div>
      <div class="modal-body">
        <p>Editing todo: {{currentText}}</p>
        <div class="row">
          <div class="col-md-12">
            <!-- THIS IS WHERE I WANT THE INITAL TEXT -->
            <input id="edit-todo-modal-input" type="text" class="form-control" [(ngModel)]="currentText">
          </div>
        </div>
      </div>
      <div class="modal-footer">
        <button type="button" class="btn btn-primary">Save changes</button>
        <button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button>
      </div>
    </div>
  </div>
</div>

editdialog.component.ts

import { Component } from '@angular/core';
import { FormsModule } from '@angular/forms';
import { ListComponent } from './list.component';
import { Injectable } from '@angular/core';

declare var jQuery : any;

@Injectable()
@Component({
  selector: 'edit-todo-dialog',
  templateUrl: './editdialog.component.html',
  styleUrls: ['./editdialog.component.css']
})
export class EditTodoDialogComponent{

  currentText: string = "";
  index: number;


  /* I want to use this method to set the initial value */
  show(index: number, text: string): void {
    this.currentText = text;
    this.index = index;

    jQuery("#edit-todo-modal-input").val(this.currentText); // I don't want to use jQuery for showing the initial value, however this works
    jQuery("#edit_todo_modal").modal(); // show bootstrap modal
  }
}

Thanks in advance.

UPDATE

The show()method gets called from this component

import { Component } from '@angular/core';
import { ListService } from './list.service';
import { OnInit } from '@angular/core';
import { EditTodoDialogComponent } from './editdialog.component';

/**
 * The main todo list component
 */

@Component({
  selector: 'list-component',
  templateUrl: './list.component.html',
  styleUrls: ['./list.component.css'],
  providers: [ListService, EditTodoDialogComponent]
})
export class ListComponent implements OnInit {

  private listService: ListService;
  private editTodoDialog: EditTodoDialogComponent;
  /* ... */


  constructor(listService: ListService, editTodoDialog: EditTodoDialogComponent) {
    this.listService = listService;
    this.editTodoDialog = editTodoDialog;
  }

  ngOnInit(): void {
    this.getTodos();
  }

  /* ... */

  // TO BE IMPLEMENTED

  showEditTodoDialog(index: number) : void {
    this.editTodoDialog.show(index, this.todos[index]);
  }
}

The event is hooked like this:

<li class="list-group-item" *ngFor="let todo of todos; let i = index">
        <div class="todo-content">
          <p class="todo-text" (dblclick)="showEditTodoDialog(i)">
            {{todo}}
          </p>
        </div>
        <div class="todo-close">
          <button (click)="removeTodo(i)" class="btn btn-danger btn-sm">
              <i class="fa fa-remove"></i>
            </button>
        </div>
      </li>
7
  • 1
    this.currentText = text; should work Commented Aug 29, 2017 at 9:43
  • Where do you call show method? Commented Aug 29, 2017 at 9:49
  • There is a second component, which calls this component's show method. The "parent" component's method is bound to a double click event. Commented Aug 29, 2017 at 9:55
  • Could you please share that piece of code? Commented Aug 29, 2017 at 9:56
  • May I ask a somewhat unrelated question - what does adding '@Injectable()' to a component do? Commented Aug 29, 2017 at 10:06

2 Answers 2

1

The problem is that you are calling the show from ListComponent by using the componentReference.

You should not do that to pass information between components .

You should either use a @Input and @Output i:e Event Emitters if these component have Parent child relationship else the best way is to go for Shared Services where once you load he data to the service the other component is notified of the change and subscribes to the new data.

More info on how to use parent child link

More info on how to use shared serviceslink

Sign up to request clarification or add additional context in comments.

1 Comment

@Input did the trick. For future reference, this is the API page that helped me debunk this. angular.io/guide/component-interaction
0

Have you tried value?:

 <input id="edit-todo-modal-input" type="text" class="form-control" [value]="currentText" ngModel>

For objects, use ngValue:

 <input id="edit-todo-modal-input" type="text" class="form-control" [ngValue]="currentText" ngModel>

3 Comments

I did: <input id="edit-todo-modal-input" type="text" class="form-control" [value]="currentText" [(ngModel)]="currentText"> It doesn't do anything. If I remove the ngModel attribute the model doesn't update on input
You tried this - <input id="edit-todo-modal-input" type="text" class="form-control" [value]="currentText" ngModel> ? notice ngModel at the end. It should create a FormControl instance from where you can manipulate values inserted by user
I copypasted this. What happens, is that not only does it not set the default value, but it doesn't seem to update the model either: I do not see the input's value above the input (notice the <p>{{currentText}}</p> above the input)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.