How to update a parent component from a child component

In AngularJS 1.5+, components follow a unidirectional data flow, meaning that child components cannot directly modify parent component data. Instead, AngularJS provides mechanisms like one-way binding (<) and callback functions (&) to allow child components to update the parent component.


1. Methods to Update a Parent from a Child

There are three main ways to update a parent component from a child:

  1. Using & binding (Best Practice) → Parent passes a callback function to child.
  2. Using a shared service → Useful when multiple components share data.
  3. Using $scope.$emit() and $scope.$on() → Used in $scope-based applications but less recommended.

2. Updating Parent Using & Binding (Recommended)

This is the best and most AngularJS-friendly approach.

  • The parent component passes a function to the child component.
  • The child component calls this function when an event occurs (like a button click).
  • The parent component updates its data accordingly.

Step 1: Parent Component (parentComponent)

  • Defines the updateMessage() function.
  • Passes it to the child using & binding.
app.component('parentComponent', {
template: `
<div>
<h3>Parent Component</h3>
<p>Message: {{$ctrl.message}}</p>
<child-component on-update="$ctrl.updateMessage(newMessage)"></child-component>
</div>
`,
controller: function() {
this.message = "Hello from Parent";

this.updateMessage = function(newMessage) {
this.message = newMessage; // Update parent data
};
}
});

The parent provides the updateMessage() function to be called by the child.


Step 2: Child Component (childComponent)

  • Defines a button that calls onUpdate({ newMessage: "Updated from Child!" }).
app.component('childComponent', {
bindings: {
onUpdate: '&' // Accepts function reference from parent
},
template: `
<div>
<h3>Child Component</h3>
<button ng-click="$ctrl.sendUpdate()">Update Parent</button>
</div>
`,
controller: function() {
this.sendUpdate = function() {
this.onUpdate({ newMessage: "Updated from Child!" }); // Call parent function
};
}
});

The child calls onUpdate(), triggering the parent’s updateMessage().
The parent component updates its message, reflecting the change.


3. Using a Shared Service (When Siblings Need to Update Parent)

If multiple components (e.g., siblings) need to update the parent, a service can manage shared data.

Step 1: Create a Shared Service

app.factory('MessageService', function() {
let message = "Hello from Parent";
let callback = null;

return {
setMessage: function(newMessage) {
message = newMessage;
if (callback) callback(newMessage); // Notify parent
},
getMessage: function() {
return message;
},
subscribe: function(cb) {
callback = cb;
}
};
});

The service stores the message and notifies the parent when updated.


Step 2: Parent Component (parentComponent)

app.component('parentComponent', {
template: `
<div>
<h3>Parent Component</h3>
<p>Message: {{$ctrl.message}}</p>
<child-component></child-component>
</div>
`,
controller: function(MessageService) {
let ctrl = this;
ctrl.message = MessageService.getMessage();

MessageService.subscribe(function(newMessage) {
ctrl.message = newMessage;
});
}
});

The parent subscribes to the service to update its message when notified.


Step 3: Child Component (childComponent)

app.component('childComponent', {
template: `
<div>
<h3>Child Component</h3>
<button ng-click="$ctrl.updateMessage()">Update Parent</button>
</div>
`,
controller: function(MessageService) {
this.updateMessage = function() {
MessageService.setMessage("Updated from Child!"); // Updates service message
};
}
});

The child updates the message via MessageService, and the parent automatically updates.
Best for complex applications with multiple components sharing data.


4. Using $scope.$emit() and $scope.$on() (Less Recommended)

If working with older $scope-based applications, you can use $emit() in the child and $on() in the parent.

Step 1: Parent Listens for Event

app.component('parentComponent', {
template: `
<div>
<h3>Parent Component</h3>
<p>Message: {{$ctrl.message}}</p>
<child-component></child-component>
</div>
`,
controller: function($scope) {
let ctrl = this;
ctrl.message = "Hello from Parent";

$scope.$on('messageUpdated', function(event, newMessage) {
ctrl.message = newMessage;
});
}
});

Parent listens for messageUpdated event and updates message.


Step 2: Child Emits Event

app.component('childComponent', {
template: `
<div>
<h3>Child Component</h3>
<button ng-click="$ctrl.sendUpdate()">Update Parent</button>
</div>
`,
controller: function($scope) {
this.sendUpdate = function() {
$scope.$emit('messageUpdated', "Updated from Child!");
};
}
});

Child emits an event to notify the parent.

This method is less recommended because:

  • $emit() and $on() rely on $scope, which is not used in newer AngularJS components.
  • Harder to debug and scale.
  • Use services or & binding instead.

5. Comparison of Methods

MethodUse CaseProsCons
& Binding (Callback)Direct child-to-parent updatesSimple, built-in, recommendedOnly works for direct parent-child
Shared ServiceMultiple components updating parentWorks across unrelated componentsRequires service setup
$emit & $on$scope-based appsWorks without additional setupNot recommended for components

6. When to Use Each Approach

Use & binding when the child directly updates the parent.
Use a service when multiple components share the same data.
Avoid $emit and $on in modern AngularJS applications.

Leave a Reply

Your email address will not be published. Required fields are marked *