angularjs dynamic model in directive from json object - angularjs

I have a json file of objects that store the properties to be used in a directive.
I want to use the json obj model value in the directive, but nothing I am trying is working.
Anyone have any ideas what I am doing wrong / missing? I find this very confusing.
Hope someone can help been trying this for days now!
Edit::
I have a $http service that gets and returns the Json object and I can access the properties fine.
I am specifically trying to use the value of the json obj model property -- "model" : "ticketData.contactname" as the dynamic value of the ng-model.
If I just use the ticketData.contactname obj then it works fine and I can edit the model value, but if I try and use the string from the Json obj then it just prints the string into the input box.
I do not know what to do. I am sure it is something basic I am missing.
Thanks in advance
Json sample:
[
{
"inputsContact" : [
{
"labelName" : "Contact Name",
"placeholder" : "Enter your name",
"model" : "ticketData.contactname",
"type" : "text"
}
}
]
Html sample:
<text-input-comp inputdata="contactName" ng-model="contactModel"> </text-input-comp>
Directive text-input-comp:
.directive('textInputComp', [ '$compile', function($compile){
return {
restrict: 'E',
scope: {
inputData: '=inputdata',
modelData: '=ngModel'
},
templateUrl: '/app/views/partials/components/textInputComp.html'
}
}]);
Directive template sample:
<label> {{ inputData.labelName }} </label>
<input type="text" ng-model="modelData" ng-model-options="{ getterSetter: true }" placeholder="{{ inputData.placeholder }}" />
<div ></div>
Controller sample:
$scope.contactName = $scope.inputData[0].inputsContact[0];
$scope.contactModel = $scope.inputData[0].inputsContact[0].model;

i think u need to get the json file first then do all the manupilation
have a look at this code
<!DOCTYPE html>
<html>
<script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.4.8/angular.min.js"></script>
<body>
<div ng-app="myApp" ng-controller="customersCtrl">
<ul>
<li ng-repeat="x in myData">
{{ x.Name + ', ' + x.Country }}
</li>
</ul>
</div>
<script>
var app = angular.module('myApp', []);
app.controller('customersCtrl', function($scope, $http) {
$http.get("customers.json").then(function (response) {
$scope.myData = response.data.records;
});
});
</script>
</body>
</html>
What u were missing is this
Just replace the customer.json file with your json and u are good to go
and
1.$http is service responsible for communicating with other file. $http says get file from ‘js/data.json’ and if the operation is a ‘success’ then execute a function holding the ‘data’ which it got automatically from data.json file
to make u understand.
2.A one more line above: [‘$scope’, ‘$http’, function($scope, $http){ … }] is little bit tricky: it takes an array holding two objects one is $scope and other is a service i.e $http. The reason we have this in array is angularJS automatically minifies code which means it removes extra spaces and shorten variable names for faster performance but sometimes this minification causes trouble so we just told controller NOT to minify $scope, $http services and function inside array.

Related

Share $scope between DOM elements with same ng-controller

I'm stuck with something (I've been reading similar questions but none of them get me to the solution).
I have 2 DOM elements (let's say 2 div's) with different id's but the same ng-controller (this is for basic example, in my real app I have 2 differente pages but works the same).
<div id="layer1" ng-controller="appCtrl">
<select ng-model="selectedType" ng-options="type.label for type in ptype track by type.value" ng-change="changeType(selectedType.value)"></select>
</div>
<div id="layer2" ng-controller="appCtrl">
<select ng-model="selectedType" ng-options="type.label for type in ptype track by type.value" ng-change="changeType(selectedType.value)"></select>
</div>
And in JS
var myAppModule = angular.module('myApp', [])
.factory('selectedType', function(){
return{}
})
.controller('appCtrl', ['$scope',function($scope){
$scope.ptype = [
{
value: 1,
label:'Kg'
},
{
value: 2,
label:'Pza'
}];
selectedType = $scope.ptype[0];
$scope.changeType = function(value){
if(value==1){selectedType = $scope.ptype[0];}
else{selectedType=$scope.ptype[1];}
};
}])
As you can see I have the options for the SELECT and the ng-model, what I need is when change the selected value in any SELECT (doesn't matter which DIV) the other gets updated too.
Here a Plunker with code SEE HERE.
Thanks!
Using a Shared service like your attempt:
you are in the good way but you just forgot that :
1 - you use the scope in ng-model,
2 - to have 2 way data binding for factory,
bind the factory itself to a scope,
and use an item inside the factory not the factory itself (eg: data).
code:
.factory('selectedType', function(){
return {
data: {} // <---- We use 'data' here for example
}
})
and in the controller now:
.controller('appCtrl', ['$scope', 'selectedType',function($scope, selectedType) {
$scope.selectedType = selectedType; // <-- Not the selectedType.data (Important)
/* but the factory object */
$scope.ptype = [
{
value: 1,
label:'Kg'
},
{
value: 2,
label:'Pza'
}];
$scope.selectedType.data = $scope.ptype[0];
})
Now we dont need the ng-change at all:
<div id="layer1" ng-controller="appCtrl">
<select ng-model="selectedType" ng-options="type.label for type in ptype track by type.value"></select>
</div>
<div id="layer2" ng-controller="appCtrl">
<select ng-model="selectedType" ng-options="type.label for type in ptype track by type.value"></select>
</div>
plunker: https://plnkr.co/edit/5qg45F?p=preview
NB: Instead of using shared service, you can also use $rootScope or $scope.$parent for that.

ng-bind not showing scope variables {{ }}

test.html (my template):
<span data-ng-bind="emailSent.info"></span>
js:
$scope.resetPasswordEmail = "my#email.here";
// info is taken from a database with different languages
$scope.emailSent = {
info: getInfoFromDatabase() // returns: 'Confirmation email sent to {{resetPasswordEmail}}, check your email.'
};
angular.element(document.body).append($compile($templateCache.get('test.html'))($scope));
However this results in the following in the span on the page:
Confirmation email sent to {{resetPasswordEmail}}, check your email.
I'm attempting to do "nested" scope variables. Do I have to re-compile the compiled template again. Or is there a proper angularjs way of achieving this.
Based on your updated question, I see why you're doing this.
The key to do it is to use $interpolate:
angular.module('app', []).
controller('Ctrl', function($scope, $interpolate, $compile){
$scope.resetPasswordEmail = "my#email.here";
$scope.emailSent = {
info: $interpolate(getInfoFromDatabase())($scope)
};
function getInfoFromDatabase(){
return 'Confirmation email sent to {{resetPasswordEmail}}, check your email.'
}
angular.element(document.body).append($compile('<span data-ng-bind="emailSent.info"></span>')($scope));
})
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="app" ng-controller="Ctrl"></div>

How do i access a dynamically generated ng-model value of an input field using $scope.$watch in angularjs

I want to access a dynamically generated angular-ngmodel
value of an input field using $scope.$watch.
This is my code snippet below:
<body ng-app="myApp" ng-controller="myCtrl">
<form>
<input type="text" ng-model="<?php echo $product->id ?>" name="prid" />
<input type="submit" value="Add to Cart" ng-click="yea()"/>
</form>
</body>
<script>
var app = angular.module('myApp', []);
app.controller('myCtrl', function($scope) {
$scope.yea = function() {
$scope.$watch('xxx', function(){
var test = angular.copy($scope.xxx);
alert(test);
})
};
});
</script>
What I want to do actually: i want to get the dynamic generated value of
the text field above, then pass it through angularJS to a php variable.
So, I thought of the code above but got stucked (do not know what the xxx
wud be). Please, am I doing it the wrong way or is there any solution to
the code above?
Thanks
You could create your own directive:
<my-input my-input-id="{{'<?php echo $product->id ?>'}}"></my-input>
This way php should replace its code with the id, which you will then be able to use in your directive:
app.directive('myInput', function() {
return {
restrict: 'E',
scope: {
myInputId: '#'
},
template: '<input ng-model="myInputId" />'
};
});
Note that I haven't tested if this code really works. If you would create a plunkr or jsfiddle, I will be more than happy to take a look.
But I would personally never print out php in a way like this. Whenever I worked with PHP and Angular, I did HTTP calls from Angular to a PHP API. This way you have a clear separation between your Angular and PHP code.
You can use ngInit to initialize your model, like
<input type="text" ng-init="initPrid(<?php echo $product->id ?>)" ng-model="prId" name="prid" />
And then inside your controller add
$scope.initPrid = function(id) {
$scope.prId = id;
};

what is the way to iterate the $resource.get other than doing $promise.then

Once I receive the document say $scope.var = $resource.get(/*one record*/).. I would need to read the received nested object structure (which is now in $scope.var) in order to display each and every field.
I am not able to access the key-value pairs that are present in the $scope.var. So I found a way in doing this using $scope.var.$promise.then(callback) but the format of the $scope.var is changed.
for example:
before parsing:
When I console to see what is in $scope.var, it shows as -
Resource: {$Promise: Promise, $resolved: false}
/*key-value pairs of the object*/
after parsing using $promise.then:
Here the console says
Object {_id: "...", ...}
/*key-value pairs of the object*/
Because of the above format difference I am facing the problem when trying to $update using $resource. Which says $update is not a function.
Is there any other way to access key-value pairs from the $resource.get other than using $promise.then?
Edit: Here is my original code:
Contact.service.js
'use strict';
angular.module('contacts').factory('Contact', ['$resource', function($resource) {
console.log('Iam cliked');
return $resource('/api/contacts/:id', {id: '#_id'}, {
update: {
method: 'PUT'
}
});
}]);
EditController.js
'use strict';
angular.module('contacts').controller('EditController', ['$scope', '$stateParams' ,'$location', '$rootScope', 'Contact',
function($scope, $stateParams, $location, $rootScope, Contact) {
$rootScope.PAGE = 'edit';
$scope.contact = {};
$scope.singleContact = Contact.get({ id: $stateParams.id});
console.log($scope.singleContact);
$scope.singleContact.$promise.then(function(data){
angular.forEach(data, function(value, key) {
if(key !== 'additions')
$scope.contact[key] = value;
else {
angular.forEach(data.additions, function(value, key) {
$scope.contact[key] = value;
});
}
});
console.log($scope.contact);
});
/*parsing my received nested json doument to have all straight key-value pairs and binding this $scope.contact to form-field directive 'record=contact'
I am successful doing this and able to display in web page but when I try to $update any of the field in the webpage it doesnt update. Because it is not being Resource object but it is just the object
please see the images attached[![enter image description here][1]][1]*/
$scope.delete = function(){
$scope.contact.$delete();
$location.url('/contacts');
};
}
]);
Edit.html
<section data-ng-controller='EditController'>
<h2>{{contact.firstName}} {{contact.lastName}}</h2>
<form name='editContact' class='form-horizontal'>
<form-field record='contact' recordType='contactType' field='firstName' required='true'></form-field>
<form-field record='contact' recordType='contactType' field='lastName' required='true'></form-field>
<form-field record='contact' recordType='contactType' field='{{k}}' ng-repeat=' (k, v) in contact | contactDisplayFilter: "firstName" | contactDisplayFilter: "lastName" | contactDisplayFilter: "__v" | contactDisplayFilter: "_id" | contactDisplayFilter: "userName"'></form-field>
<new-field record='contact'></new-field>
<div class='row form-group'>
<div class='col-sm-offset-2'>
<button class='btn btn-danger' ng-click='delete()'>Delete Contact</button>
</div>
</div>
</form>
form-field.html
<div class='row form-group' ng-form='{{field}}' ng-class="{'has-error': {{field}}.$dirty && {{field}}.$invalid}">
<label class='col-sm-2 control-label'>{{field | labelCase}} <span ng-if='required'>*</span></label>
<div class='col-sm-6' ng-switch='required'>
<input ng-switch-when='true' ng-model='record[field]' type='{{recordType[field]}}' class='form-control' required ng-change='update()' ng-blur='blurUpdate()' />
<div class='input-group' ng-switch-default>
<input ng-model='record[field]' type='{{recordType[field]}}' class='form-control' ng-change='update()' ng-blur='blurUpdate()' />
<span class='input-group-btn'>
<button class='btn btn-default' ng-click='remove(field)'>
<span class='glyphicon glyphicon-remove-circle'></span>
</button>
</span>
</div>
</div>
<div class='col-sm-4 has-error' ng-show='{{field}}.$dirty && {{field}}.$invalid' ng-messages='{{field}}.$error'>
<p class='control-label' ng-message='required'>{{field | labelCase}} is required.</p>
<p class='control-label' ng-repeat='(k, v) in types' ng-message='{{k}}'>{{field | labelCase}} {{v[1]}}</p>
</div>
function in form-field.js directive
$scope.blurUpdate = function(){
if($scope.live!== 'false'){
console.log($scope.record);
$scope.record.$update(function(updatedRecord){
$scope.record = updatedRecord;
});
}
};
So in the above $update gives error. saying not a function.
I want the same format in $scope.singleContact and $scope.contact. How can I achieve this?
I don't know if I understand but you want something like this:
Contact.get({id: $stateParams.id}, function (contact){
$scope.var = contact;
});
right?
It will return te promise and you will be able to use the data before loading the templates
Okay, a couple things:
Promises will not return values synchronously
You have to use a then function call. The line
$scope.singleContact = Contact.get({ id: $stateParams.id});
will not put your data into the $scope.singleContact variable immediately because that line returns a Promise and goes onto the next line without waiting for the web request to return. That's how Promises work. If you aren't familiar with them, it might not be a bad idea to read up on them. A consequence of this is that everything inside your controller (or wherever this code is) that needs a working value in $scope.singleContact needs to be inside of a then block or in some way guaranteed to be run after the promise is resolved.
So I think you want (as #EDDIE VALVERDE said):
Contact.get({ id: $stateParams.id}, function(data) {
$scope.singleContact = data;
$scope.contact = data;
});
I'm not sure what the rest of the code is doing but it looks to me like it is trying to do a deep copy of $scope.singleContact. My guess is that you're just doing this cause the promise stuff wasn't working and you can remove it...
Let me know if I missed something.
Ah, now I think I understand. Okay, for 1 I would not add $resource objects to your scope. IMO the scope is intended to be a Model in the MVC paradigm. A $resource is kindof like a model, but it's performing network calls and it's got a bunch of stuff other than data. If you put $resource in your model you remove any clear layer where you can manipulate and transform the data as it comes back from the server. And I'm sure there are other reasons. So I would not add $resource objects like Contact directly to the scope. That being said, I think you want to add a new update function, like you did with delete, only something like this:
$scope.update= function(args){
//make network call and update contact
Contact.$update({/*data from args?*/});
//get the data i just saved
Contact.$get({/* id from args */}, function(result) {
$scope.contact = result;
});
//other stuff?
};
That's my first thought, anyway...

Angularjs - Using controller

I am new to Angular.js. I currently have the following html code, where I define my div with my file html ( ng-include ) and my controller ( ng-controller ):
<div id="customerinformation-maxi" ng-include="'pages/customerinformation-maxi.html'" ng-controller="customerInformationMaxiController" class="col-md-12"></div>
This is the html code for the called html in directive ng-include ( customer-information.html ):
<div class="row">
<div class="col-md-2">
<span>Customer Number</span>
<span>{{customer.number}}</span>
</div>
<div class="col-md-2">
<span>Portfolio</span>
<span>{{custom.portfolio}}</span>
</div>
</div>
This is the js controller:
angularRoutingApp.controller('customerInformationMaxiController', function($scope, $http) {
//Here i need to load the model variable with a literal text {{customer.number}} and {{customer.portfolio}}, how could do it? using scope object? with a json file?
});
Here I need to load the model variable with a literal text {{customer.number}} and {{customer.portfolio}}.
How could do it? Using scope object? With a json file?
Thanks for any help.
Yes, you should do it using the $scope object.
To get a general overview, here is a hello-world example:
<div ng-controller="HelloController">
{{ helloMessage }}
</div>
And in you controller's code (js file or script tag into the html):
var myApp = angular.module('myApp',[]);
myApp.controller('HelloController', ['$scope', function($scope) {
$scope.helloMessage= 'Hello World!';
}]);
But I foresee some nesting in the provided snippet of your question, so you 're probably dealing with a collection of objects which means that you have to iterate through it, in the html part, using the ng-repeat directive, like:
<tr ng-repeat="customer in customers>
<td>{{customer.number}}</td>
<td>{{customer.portfolio}}</td>
</tr>
So, your controller's functionality should contain the customers object, like:
angularRoutingApp.controller('customerInformationMaxiController', function($scope, $http) {
var customers=[
{
number:'123',
portfolio: 'blah blah'
},
{
number:'124',
portfolio: 'blah blah'
},
{
number:'125',
portfolio: 'blah blah'
}
];
});
For further reference, you could read two respective example I have written:
Angular.js Controller Example
Angular.js JSON Fetching Example
The second one is only to see a sample usage of traversing collections, it is not meant that you have to use json, as you stated in your question; but I see that you also defined the $http service in your controller, so if it's about data that are going to be fetched from a remote destination, the JSON Fetching Example should probably help you better).
You should use scope objects to give values to your modal variables.
angularRoutingApp.controller('customerInformationMaxiController', function($scope, $http) {
$scope.customer.number = 'sample number';
$scope.customer.portfolio = 'sample portfolio';
});

Resources