AngularJS assign variables to view's scope - javascript

I have a somewhat deep JSON object I am trying to using in an HTML template.
{
"service": {
"name": "example",
"url": "abc.com",
"template": "/abc/def/v1",
"metadata": {
"password": "dontguessme",
"username": "supereasy"
}
}
}
I am including a template with the following HTML code.
<div class="modal-body" ng-include="service.instructionsTemplate"> </div>
In the template there is the following.
<h1>Some example content</h1>
{{service.metadata.password}}
My question is instead of referencing the field password via service.metadata, is there a way I can reference it with just the variable password.
I was trying to dig through some of the Angular docs around scoping and templates but came up empty. I saw you can use ng-init.
I was able to use ng-init="metadata = service.metadata" and was able to reference the field password in the template via metadata.password.
However I would just like to reference it by password.
Any ideas?

You already did ng-init="metadata = service.metadata", why not going a step further and do ng-init="password = service.metadata.password"?
Another way would be to bind $scope.password = service.metadata.password inside the controller thayou're using on that page
Edit: OP asked a more general solution
If you don't know the property names, then your best move would be to bind the metadata object, like you already did, and then iterate through its properties using ng-repeat
in your controller:
$scope.metadata = service.metadata
in your template (view):
<h1>Some example content</h1>
<ul>
<li ng-repeat="element in metadata">{{element}}</li>
</ul>

You can easily set the password to something inside the controller:
app.controller('MainCtrl', function($scope) {
$scope.name = 'World';
$scope.data = {
"service": {
"name": "example",
"url": "abc.com",
"template": "/abc/def/v1",
"metadata": {
"password": "dontguessme",
"username": "supereasy"
}
}
};
$scope.password = $scope.data.service.metadata.password;
});
Here is a demo: http://plnkr.co/edit/KrKeLIP2ANd0rl5NLywF?p=preview

Related

How to display nested JSON objects using ng-repeat with Ionic framework?

I am developing a simple hybrid mobile app using the Ionic framework. When you search for a last name, a GET request is sent to retrieve all matching last names, and then displays their corresponding ID's. I am having an issue displaying the returned data from the JSON object.
Below is the html page:
<ion-view view-title="Account" ng-controller="AccountCtrl">
<ion-content>
<div class="list">
<div class="item item-input-inset">
<label class="item-input-wrapper">
<input type="text" placeholder="Search" ng-model="name">
</label>
<button class="button button-small" ng-click="searchUser(name)">
Go
</button>
</div>
</div>
<div>
<ul ng-repeat="user in $results">
<li>{{user.id}}</li>
</ul>
</div>
</ion-content>
Next is the js file that successfully returns a populated JSON object with everything I need.
angular.module('starter.controllers', [])
.controller('AccountCtrl', ['$scope', '$http', function ($scope, $http) {
$scope.searchUser = function (name) {
$http.get('https://notrelevantforthis/searchLastName?=' + name).then(function (response) {
console.log(response.data)
//Assign JSON obj to results to repeat through and display data
$scope.results = response.data;
//To show the actual JSON object is returned
//var jsonStr = JSON.stringify($scope.results);
//document.body.innerHTML = jsonStr;
}, function (error) {
console.log(error)
});
};
}]);
Now the important part is the structure of the JSON object itself. I think this is where I am getting confused. The structure is like the following:
{
"response": {
"totalFound": 275,
"start": 0,
"acc": [
{
"id": [
"1"
],
"first_name": [
"Joe"
],
"last_name": [
"Smith"
]
},
{
"id": [
"2"
],
"first_name": [
"John"
],
"last_name": [
"Doe"
]
}]}
}
My problem is iterating through the JSON object using ng-repeat I think. For some reason none of the data is being displayed, but the object is definitely there when looking at the console. Any help or direction in what I am doing wrong would be much appreciated, as I am new to this and have been trying to find the correct way to do this.
EDIT:
Tried using collection-repeat as well offered by the ionic framework but was getting stack limit errors.
When you're assigning response.data to $scope.results, you're literally assigning the HTTP's response body to it, which is the whole JSON object that you have in your question. You would need to actually point to response.data.response.acc if you wanted to ng-repeat through those accounts.
In your template, it should just be ng-repeat="user in results", without the $ in front of results.
Your JSON object lists the id for each account as an array, I'd recommend just giving the literal value without the array, otherwise in your ng-repeat you'll have to use {{user.id[0]}} to actual print the value without printing the array itself.
I've created an example for you here: http://plnkr.co/edit/GYeF4FzVHl8Og5QTFcDx?p=preview

Outputting JSON Data in Angular Expressions

My PHP script returns this JSON data:
{
"userData": {
"userName": "knows_nothing",
"userFullName": "Jon Snow",
"userMoney": "124.01"
}
}
How can I access the variables (userName etc) in my webpage?
eg:
JS
var app = angular.module('dashboard', []);
app.controller('userDataCtrl', function($scope, $http) {
data = "{query:'userData'}"
$.post("api/mysql.php", {query:'userData'})
.then(function (response) {$scope.userData = response.userData;});
});
HTML
<div ng-app="dashboard">
<div ng-controller="userDataCtrl">
<h1> Username: {{ userData.userName }} </h1>
<p> Balance: {{ userData.balance }} </p>
</div>
</div>
This has been driving me insane for hours :(
This is what it outputs when I `console.log(response.userData)
Object { userName: "knows_nothing", userFullName: "Jon Snow", userMoney: "124.01" }
According to $http documentation you should read the response from response.data. So, in your case:
...
.then(function (response) {$scope.userData = response.data.userData;});
should do the trick.
Maybe you have to declare the $scope.userData variable outside of the then-function
check if your response is array, if array then you need to do something like this,
$scope.userData = response[0].userData.
If still not getting solution please share or response format.Entire response structure.

ng-repeat won't repeat array of data

I am pulling in a JSON file using Angular's $http, but I can't get the formatting right to use ng-repeat for an array of data.
For brevity's sake, here is a sample piece of what I'm working with...
{
name:"Pete",
phone: {
brand: "Nexus",
OS: "Android",
contacts: [
"Alexis",
"Billy",
"Chuck",
"Danny"
]
}
}
Then my ng code is
function($scope, $http) {
$http.get('/my/url')
.success(
function(data){
$scope.contacts = data.phone.contacts;
and my HTML is
<div ng-repeat="names in contacts">
{{names}}
</div>
Only it isn't returning anything. I feel like I am missing a set of [] somewhere?
In JSON:
conAtacts: [
"Alexis",
"Billy",
"Chuck",
"Danny"
]
On view:
<div ng-repeat="names in contacts">
{{names}}
</div>
conAtacts != contacts
Also, you have missed one bracket in JSON.
Should be:
{
name:"Pete",
phone: {
brand: "Nexus",
OS: "Android",
contacts: [
"Alexis",
"Billy",
"Chuck",
"Danny"
]
}
}
Can it be reasons of issue?
Your problem could simply be because you didn't respect the widely recommended practice of the 'point' when you use values that can evolve in AngularJS.
Create an object in the scope :
$scope.dataScope = {}
then in your method
function($scope, $http) {
$http.get('/my/url')
.success(
function(data){
$scope.dataScope.contacts = data.phone.contacts;
and in your html
<div ng-repeat="name in dataScope.contacts">
{{name}}
</div>
Thanks everyone for the as always quick responses. This was a case of sleep deprivation and overthinking things on my part and I left out the ng-controller for the div that the ng-repeat was in.
<div **ng-controller="myCtrl"** ng-repeat="names in contacts">
{{names}}
</div>

AngularJS How to use RESTful with factory module

I have been getting an error to make RESTful code for 2 hours.
I have one file has a controller here
angular.module('orderToBeShippedApp',['ng','projectService'])
.controller('orderCtrl',function($scope, Project){
Project.query(function(data){
alert(data);
$scope.projects = data;
});
});
Here is my fatory which is called 'project'.
angular.module('projectService',['ng','ngResource'])
.factory('Project',function($resource){
return $resource('api/url/:projectId.json',{},{
query:{
method:'get',
params: {projectId:"test"},
isArray: false
}
});
});
My html:
<div ng-controller = "orderCtrl" class ="col-sm-8 col-md-9">
<!--Body content -->
<div ng-repeat = "project in projects">
<h2>{{project.name}}</h2>
</div>
</div>
My json is something like
[
{
"age": 0,
"id": "a",
"imageUrl": "a0.jpg",
"name": "b",
"snippet": "Tbaa."
},
{
"age": 1,
"id": "mo",
"imageUrl": "assets/images/phones/mo.0.jpg",
"name": "M\u2122",
"snippet": "The Ned by Android 3.0 (Honeycomb)."
}
]
It doesn't give me any error message on the browser. it seems having a problem on factory function.
Could anyone help me to fix it?
You should change your binding to be name, not ProjectName based on your model definition:
<div ng-controller = "orderCtrl" class ="col-sm-8 col-md-9">
<!--Body content -->
<div ng-repeat = "project in projects">
<h2>{{project.name}}</h2>
</div>
Also, to use ngResource you need to remember to add a script reference to: angular-resource:
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.2.19/angular-resource.min.js"></script>
UPDATE:
Remove 'ng' Dependency
Pass the resource to the controller as a dependency.
// resource
angular.module('projectService',['ngResource'])
.factory('Project',function($resource){
return $resource('api/url/:projectId.json',{},{
query:{
method:'get',
params: {projectId:"test"},
isArray: false
}
});
});
// controller
angular.module('orderToBeShippedApp',['projectService'])
.controller('orderCtrl',['$scope','Project', function($scope, Project){
Project.query(function(data){
alert(data);
$scope.projects = data;
});
}]);
Your factory may not be giving a console error however it may not be able to bring back the data. Your factory should be looking like this:
angular.module('projectService',['ng','ngResource'])
.factory('Project',function($resource){
return {
projects: $resource('api/url/:projectId.json', {projectId: '#test'})
}
});
}]);
In your controller it should invoke the method like this:
angular.module('orderToBeShippedApp',['ng','projectService'])
.controller('orderCtrl',['$scope','Project',function($scope, Project){
$scope.projects = Project.projects.get({id: 'test'});
}]);
UPDATE:
In order to relax chrome the xmlHttpRequest error you need to run this command from the chrome.exe folder of your machine:
"C:\Program Files (x86)\Google\Chrome\Application\chrome.exe" --allow-file-access-from-files --disable-web-security

Dynamic form in AngularJS

I'm developing a CMS for a customer, it's all based on AngularJS with its controllers, views, services, etc.
What I need is a pattern where a dynamically loaded script injects some data in an existing scope.
Ok, in human words: I have a form managed by a controller. This form has several preset fields. These fields are managed by an array of the scope, something like:
$scope.fields = [
{ type: "text", name="first_name" },
{ type: "text", name="last_name" },
{ type: "email", name="email" }
];
The view prints dynamically the fields (i.e. it's a scaffolding).
When the customer log into the application I check if in his profile he has a custom script to load, if so the application appends a javascript to the DOM, the javascript file name is equal to the username of the logged user.
So, if the user is called "darko" and he has a custom script enabled, the application append this file to the DOM:
/js/customers/darko.js
Let's say that darko has further fields to show (and save) inside the form, how can I do that? I'd need to hook the controller so I can have access to its scope and then inject my fields. Something like:
var $scope = getUserFormScope();//some magic....
$scope.fields.push({ type: "text", name="skype" });
However, The form with further fields is just an example, what I really need, more generally, is a way to "hook controllers" and have access to theirs scopes.
Any idea?
SOLUTION
I've finally used the method suggested by marfarma. The custom script contains one or more partial controllers named with the same name of the controller they want to extend prefixed by Custom word, then I extend my controllers with these partial controllers. For example, my app has a controller named PageController, inside this controller I check if a CustomPageController exists:
if (typeof CustomPageController == 'function') {
angular.extend(this, CustomPageController($scope));
}
if so, I extend the main controller with the custom one.
Here is a general way to "hook controllers" and have access to their scopes - mixin your hook code via angular.extend.
function CustomUserController($scope) {
// contents of this hook controller is up to you
var _this = this;
// Mixin instance properties.
this.vocalization = getValue('vocalization',$scope.user);
this.runSpeed = getValue('runSpeed' ,$scope.user);
// Mixin instance methods.
this.vocalize = function () {
console.log(this.vocalization);
};
// Mixin scope properties.
$scope.color = color;
// Mixin scope methods.
$scope.run = function(){
console.log("run speed: " + _this.runSpeed );
};
}
function PageController($scope) {
var _this = this;
$scope.user; // this should be the current user obj, with key for custom script lookup
// Mixin Custom Script into Controller.
if (userService.hasCustomScript($scope.user)) {
angular.extend(this, new CustomUserController($scope));
}
}
As for your specific example, one way to insert arbitrary fields into a form is to build it dynamically. I use a schema form directive that might work for your situation. Given a schema that defines the model properties, and an array that specified the items their order of inclusion, the directive lays out the form.
For example (see also this working plunker, incl. add'l features):
<form class="form-inline" name="form" novalidate role="form">
<div class="row-fluid clearfix">
<h2>Sample Form</h2>
</div>
<div class="row-fluid clearfix">
<hr>
<div class="span12">
<fieldset class="span6">
<schema-form-fields
fields="side1Fields"
model="model"
schema="modelSchema"
data="requestResult"
schema-list="schema">
</schema-form-fields>
</fieldset>
<fieldset class="span6">
<schema-form-fields
fields="side2Fields"
model="model"
schema="modelSchema"
data="requestResult"
schema-list="schema">
</schema-form-fields>
</fieldset>
</div>
</div>
<div class="row-fluid clearfix">
<button
class="btn btn-primary span2 offset10"
type="submit">
Submit
</button>
</div>
</form>
// example controller with dynamic form
app.controller('HomeCtrl', ['$scope', 'schema', 'requestResult', 'dataService',
function($scope, schema, requestResult, dataService) {
$scope.modelSchema = schema.product;
$scope.model = {
factoryDate: '20160506'
};
// field name arrays - one array per column in sample layout
// insert elements into these and form should re-render
// may require explicit watch to trigger update
$scope.side1Fields = [
'productName',
'factoryDate'
];
$scope.side2Fields = [
'productType',
'timeValue'
];
// .... other controller code
}
]);
// example schema
app.value('schema', {
"product": {
"type": "object",
"title": "Product Schema",
"properties": {
"productType": {
"type": "string",
"title": "Product Type",
"showLabel": true,
"tooltip": "Product classification",
"readonly": false,
"required": true,
"class": "custom-select",
"enum": ['Bike', 'Car', 'Airplane', 'Glider', 'Stilts']
},
"productName": {
"title": "Product Name",
"showLabel": true,
"type": "string",
"tooltip": "A more descriptive name for the modeled structure.",
"readonly": false,
"required": true
},
"factoryDate": {
"title": "Factory Date",
"type": "string",
"showLabel": true,
"control": "date",
"dateFormat": "yyyymmdd", // TODO format as provided
"tooltip": "Date of manufacture.",
"dateOptions": {
autoclose: true
},
"readonly": false,
"required": true
},
"timeValue": {
"title": "Time (HHMM)",
"showLabel": true,
"type": "string",
"pattern": "([0-1]{1}[0-9]{1}|20|21|22|23)[0-5]{1}[0-9]{1}",
"timeFormat": "hhmm", // TODO format as provided
"tooltip": "Time entry.",
"readonly": false,
"required": true,
}
}
}
});

Categories

Resources