swathi anupuram swathi anupuram - 3 months ago 12
AngularJS Question

unable to bind the object from component controller to view in angular 1.5

I have a scenario where i need to bind the object from component controller to view which is the response coming from service.

when I am binding that object in html it is binding as empty object which I initialized. But after getting the response it is not updating.

Script:

(function() {
app.component('tabComponent', {
bindings: {
toggle: '<',
oUserDetails: '<'
},
templateUrl: 'components/tabComponent/tabComponent.html',
controller: tabComponentCtrl
})

function tabComponentCtrl(mainService) {
this.emailPattern = /^[_a-z0-9]+(\.[_a-z0-9]+)*@[a-z0-9-]+(\.[a-z0-9-]+)*(\.[a-z]{2,4})$/;
this.phNumberPattern = /^[\+]?[(]?[0-9]{3}[)]?[-\s\.]?[0-9]{3}[-\s\.]?[0-9]{4,6}$/;
this.namePattern = /^[a-zA-Z ]{1,15}$/;
this.aEmployeeTypes = ["option1", "option2", "option3", "xyz", "abc", "lmn"];
this.toggle = true;
this.oUserDetails = {};
/* for getting json data*/
mainService.fnGerUserDetails().then(function(response) {
this.oUserDetails = response;
console.log(this.oUserDetails); //response
}, function(response) {
alert('error')
});
console.log(this.oUserDetails); //{}
/* for updating data to read only form*/
this.fnSendData = function() {
this.toggle = true;
};
}
})();


Html:

<md-content class="tabs-color">
<md-tabs md-dynamic-height="" md-border-bottom="">
<!-- for first tab -->
<md-tab label="Tab1">
<md-content class="md-padding">
<img src="{{$ctrl.oUserDetails.img}}" height="200px" width="200px">
<div layout="column">
<form name="userForm" data-ng-submit="$ctrl.fnSendData()">
<md-input-container class="md-block">
<label>Name:</label>
<input type="text" name="userName" ng-model="$ctrl.oUserDetails.name" ng-pattern="$ctrl.namePattern" ng-readonly="$ctrl.toggle" required>
<div ng-messages="userForm.userName.$error">
<div ng-message="required">UserName is required.</div>
<div ng-message="pattern">Must be maximum 15 characters only</div>
</div>
</md-input-container>
<md-input-container class="md-block">
<label>Email:</label>
<input type="email" name="userEmail" ng-model="$ctrl.oUserDetails.email" ng-pattern="$ctrl.emailPattern" ng-readonly="$ctrl.toggle" required>
<div ng-messages="userForm.userEmail.$error">
<div ng-message="required">Email is required.</div>
<div ng-message="pattern">Email Is Invalid</div>
</div>
</md-input-container>
<md-input-container class="md-block">
<label>Phone Number:</label>
<input type="text" name="phNumber" ng-model="$ctrl.oUserDetails.phoneNumber" ng-pattern="$ctrl.phNumberPattern" ng-readonly="$ctrl.toggle" required>
<div ng-messages="userForm.phNumber.$error">
<div ng-message="required">Phone Number is required</div>
<div ng-message="pattern">Must be a valid 10 digit phone number</div>
</div>
</md-input-container>
<md-input-container class="md-block">
<label>Location:</label>
<input type="text" name="location" ng-model="$ctrl.oUserDetails.location" ng-readonly="$ctrl.toggle" ng-pattern="$ctrl.namePattern">
</md-input-container>
<label class="label">Employee Type:</label>
<md-select ng-model="$ctrl.oUserDetails.employmentType" class="md-no-underline" ng-disabled="$ctrl.toggle" md-selected-text="$ctrl.fnGetSelectedText()">
<md-optgroup label="$ctrl.aEmployeeTypes">
<md-option data-ng-repeat="type in $ctrl.aEmployeeTypes" value="{{type}}">{{type}}</md-option>
</md-optgroup>
</md-select>{{text}}
<md-input-container class="md-block" ng-if="$ctrl.oToggle.showOrg">
<label>Organization:</label>
<input type="text" name="organization" ng-model="$ctrl.oUserDetails.organization" ng-readonly="$ctrl.toggle" required>
<div ng-messages="userForm.organization.$error">
<div ng-message="required">Organization is required</div>
</div>
</md-input-container>
<md-input-container class="md-block" ng-if="$ctrl.oToggle.showExp">
<label>Experiance:</label>
<input type="text" name="location" ng-readonly="$ctrl.toggle" ng-model="$ctrl.oUserDetails.yearsOfExperiance" required>
<div ng-messages="userForm.location.$error">
<div ng-message="required">Location is required</div>
</div>
</md-input-container>
<md-input-container class="md-block" ng-if="$ctrl.oToggle.showOther">
<label>Others:</label>
<input type="text" name="others" ng-readonly="$ctrl.toggle" ng-model="$ctrl.oUserDetails.employmentType" required>
<div ng-messages="userForm.others.$error">
<div ng-message="required">Others is required</div>
</div>
</md-input-container>
<md-button type="submit" class="md-primary" aria-label="Save Data" ng-readonly="$ctrl.toggle">Send</md-button>
</form>
</div>
</md-content>
</md-tab>
</md-tabs>
</md-content>


json:

{
"status": 200,
"msg": "user details",
"devMsg": "token expired.",
"data": {
"img": "https://image.freepik.com/free-icon/user-image-with-black-background_318-34564.png",
"name": "xyz",
"email": "xyz@gmail.com",
"employmentType": "option2",
"phoneNumber": "9876543210",
"location": "Hyderbad",
"yearsOfExperiance": 5,
"organization": "abc"
}
}


Here
$ctrl.oUserDetails
is binding as
{}
instead of that response.

Ved Ved
Answer

I guess, the issue is because of using 'this' inside callback function. Here:

mainService.fnGerUserDetails().then(function(response) {
                this.oUserDetails = response;// here 'this' is callback function
                console.log(this.oUserDetails); //response  
          }

So, this (aka "the context") is a special keyword inside each function and its value only depends on how the function was called, not how/when/where it was defined. It is not affected by lexical scope, like other variables.

Try this.

function tabComponentCtrl(mainService) {
             var that = this;
            this.emailPattern = /^[_a-z0-9]+(\.[_a-z0-9]+)*@[a-z0-9-]+(\.[a-z0-9-]+)*(\.[a-z]{2,4})$/;
            this.phNumberPattern = /^[\+]?[(]?[0-9]{3}[)]?[-\s\.]?[0-9]{3}[-\s\.]?[0-9]{4,6}$/;
            this.namePattern = /^[a-zA-Z ]{1,15}$/;
            this.aEmployeeTypes = ["option1", "option2", "option3", "xyz", "abc", "lmn"];
            this.toggle = true;
            that.oUserDetails = {};
            /* for getting json data*/
            mainService.fnGerUserDetails().then(function(response) {
            that.oUserDetails = response; // assigning response to new variable.

          }, function(response) {
                alert('error')
            });

            console.log(that.oUserDetails); //{}
            /*  for updating data to read only form*/
            this.fnSendData = function() {
                this.toggle = true;
            };
        }

Edit: Using ES6 syntax:

mainService.fnGerUserDetails().then((response)=> {
                this.oUserDetails = response;
                console.log(this.oUserDetails); //response  
          }