Creating a simple directive with JSON - javascript

I am creating a simple pattern library with an index page of HTML patterns, and individual pages for each pattern.
I am thinking that I should create a "pattern" directive that would include the template for the index page patterns. Like this:
<pattern></pattern>
which would show:
<section ng-repeat="pattern in patterns | orderBy:'title'" class="pattern-type" data-anchor="{{pattern.anchor}}" id="{{pattern.id}}">
<h3>{{pattern.title}} individuals/{{pattern.anchor}}</h3>
<div class="pattern-desc" ng-show="pattern.description">
<p>{{pattern.description}}</p>
</div>
<div class="pattern" ng-include="'individuals/' + {{pattern.anchor}}"></div>
<div class="pattern-status">
Date Posted: <span class="date"> {{pattern.updated | date:'yyyy-MM-dd'}}</span>
</div>
</section>
I would create a separate "individual" directive for the individual pattern display template. My app.js look like this:
app.directive('pattern', function() {
return {
restrict: 'E',
templateUrl: 'pattern.html',
controller: function() {
$http.get('assets/js/components.json')
.then(function(result) {
$scope.patterns = result.data;
});
},
controllerAs: 'patterns'
};
});
And my JSON looks like this:
[{
"id": "alerts",
"anchor": "alerts",
"title": "Alerts",
"description": "This is a desc",
"guidelines": "",
"updated": "2015-06-26"
},
{
"id": "buttons",
"anchor": "buttons",
"title": "Buttons",
"description": "",
"guidelines": "",
"updated": "2015-04-15"
}]
However nothing is showing up. What am I missing?

Your directive controller has missing $http & $scope dependency inside its function.
Code
controller: function($scope, $http) { //<-- added dependency here
$http.get('assets/js/components.json')
.then(function(result) {
$scope.patterns = result.data;
});
},
Working Plunkr

Related

jQuery function converted to directive not working in angular

I need to load html from json file. So I found dform as best solution for that. Since it's the jQuery plugin and I need that in Angular. I am lucky that I found it's directive on jsfiddle.
The only difference is that I had my own json file and I have written the code separately. I am using service to get data from json file through http request.
After that I am using the directive similar to the jsfiddle one.
app.js
var app = angular.module('angularApp', []);
service.js
app.service('loaderService', ['$http', function ($http) {
this.getLoadedHtml = function (callback)
{
return $http.get('../source/file.json')
.then(function (res) {
callback(res.data);
});
}
}])
controller.js
app.controller('mainCtrl', ['$scope', 'loaderService', function ($scope, loaderService) {
loaderService.getLoadedHtml(function (data) {
$scope.fields = data;
});
}]);
directive.js
app.directive('dform', function () {
return {
scope: {
action: '#',
method: '#',
html: '='
},
link: function (scope, elm, attrs) {
var config = {
"action": scope.action,
"method": scope.method,
"html": scope.html
};
elm.dform(config);
}
};
})
index.html
<div class="container-fluid" ng-app="angularApp">
<div ng-controller="mainCtrl" style="background-color:green; margin-top:100px; height:1000px;">
<div class="col-sm-3" id="source-area">
<div action="index.html" method="get" html="fields" dform></div>
</div>
</div>
</div>
file.json
[
{
"type": "p",
"html": "You must login"
},
{
"name": "username",
"id": "txt-username",
"caption": "Username",
"type": "text",
"placeholder": "E.g. user#example.com"
},
{
"name": "password",
"caption": "Password",
"type": "password"
},
{
"type": "submit",
"value": "Login"
}
]
I have used jquery and dform library too.
Since I have not got any error. My array is coming fine into controller and $scope.fields is also working fine in controller. By I cannot see any html rendered? I have used the same as in jsfiddle.
Elaborating on my comment. So what I think happens is dform does not reload automatically when the html changes (just not expecting it to change). What you could do in your directive is watch on html and update dform on change:
...
link: function (scope, elm, attrs) {
var config = {
"action": scope.action,
"method": scope.method,
"html": scope.html
};
scope.$watch('html', function() {
elm.dform(config);
});
elm.dform(config);
}
...
But wait, there is more! As I mentioned, dform also supports loading external forms from server. According to documentation, that should be possible by using url subscriber. So your directive would look something like this:
app.directive('dform', function () {
return {
scope: {
action: '#',
method: '#',
url: '='
},
link: function (scope, elm, attrs) {
var config = {
"action": scope.action,
"method": scope.method,
"url": scope.url
};
scope.$watch('url', function() {
elm.dform(config);
});
elm.dform(config);
}
};
})
This eliminates the need in loader service. Now, I haven't tried this, so it maybe will require some tweaking from your side, by the idea should be clear by now.
UPDATE:
Ok, I've done a demo (which you should do next time you ask the question).
The big problem was that the config.html needed to be reassigned after change in html property. So our link function now looks like this:
link: function(scope, elm, attrs) {
scope.$watch('html', function() {
if (!scope.html)
return;
var config = {
"action": scope.action,
"method": scope.method,
"html": scope.html
};
$(elm).dform(config);
});
}
P.S. I have replaced http call with timeout, but that makes absolutely no difference.

Object not getting returned properly from Ionic service

Background: I'm making a simple Ionic project about the NYC Subway. I am using the Ionic "tabs" template, and I have a tab that lists all of the routes with their symbols (1, 2, 3, A, C, E, etc.) and the user should be able to click on any of the routes listed there and be taken to a detail page (kind of like how they have a "Chats/Chat Detail" setup in the tabs template when you start a new ionic project).
The problem is I can't seem to get the Route Detail page to load information about the selected route. Expressions like {{route.name}} and {{route.desc}} come up blank.
routes.json file (sample, filed under www/js/routes.json):
{
"routes": [{
"id": "1",
"name": "1",
"desc": "7 Avenue Local",
"className": "c123"
},
{
"id": "2",
"name": "2",
"desc": "7 Avenue Express",
"className": "c123"
},
{
"id": "3",
"name": "3",
"desc": "7 Avenue Express",
"className": "c123"
},
...
app.js:
angular.module('starter', ['ionic', 'starter.controllers', 'starter.services'])
// ...
.state("tab.routes", {
url: "/routes",
views: {
"tab-routes": {
templateUrl: "templates/tab-routes.html",
controller: "RoutesCtrl"
}
}
})
.state("tab.route-detail", {
url: "/routes/:id",
views: {
"tab-routes": {
templateUrl: "templates/route-detail.html",
controller: "RouteDetailCtrl"
}
}
});
controllers.js:
angular.module('starter.controllers', [])
// ...
/* This one works perfectly */
.controller('RoutesCtrl', function($scope, $http) {
$http.get("js/routes.json").then(function(response) {
$scope.routes = response.data.routes;
console.log($scope.routes);
});
})
/* This one does NOT work */
/* $stateParams.id returns the correct value, but $scope.route
does not store the Route returned from the service (null) */
.controller("RouteDetailCtrl", function($scope, $stateParams, Routes) {
$scope.route = Routes.getRoute($stateParams.id);
})
services.js:
angular.module('starter.services', [])
/* This is the problem */
.factory("Routes", function($http) {
return {
getRoute: function(id) {
return $http.get("js/routes.json").then(function(response) {
var routes = response.data.routes;
for(var i = 0; i < routes.length; i++) {
if(parseInt(id) === parseInt(routes[i].id)) {
return routes[i];
}
}
return null;
})
}
}
})
I think the problem has something to do with the way the JSON is coming back in services.js - is it the way my JSON is stored, or the way I'm "parsing" it on the receiving end? The "RoutesCtrl" works just fine, but I can't seem to get the route detail working no matter what variation of response I use in services.js - I have tried response, response.data, response.data.routes, nothing works.
route-detail.html: (as you can see, {{route.whatever}} refers to the $scope.route in controllers.js but it's not getting stored).
<ion-view view-title="{{route.name}}">
<ion-content class="padding">
<h2>{{route.name}}</h2>
<h2>{{route.desc}}</h2>
<p>This is the detail page.</p>
</ion-content>
</ion-view>
The problem is not with the routes object as the same code works fine in RoutesCtrl but with the way youare handling the response in RouteDetailCtrl. The response returned from Route service is not an primitive javascript values but a promise and you need to handle the promise correctly to get your response:
.controller("RouteDetailCtrl", function($scope, $stateParams, Routes) {
Routes.getRoute($stateParams.id)
.then(function (response) {
$scope.route = response;
});
})

How to access one directive scope value to other directive in angularjs?

Actually my requirement is to get the one directive scope to another directive and need to perform the two way binding.
I need to change that JSON values whenever the ng-model will get change. In the below example JSON having rowset with attributes. These attribute names i have to bind the with control(textbox) like ng-model=CuId. So whenever the corresponding attributes value will get change the JSON need to be update.
Source Code:
var app = angular.module("myApp", []);
app.directive("main", function() {
});
app.directive("sub1", function() {
return {
restrict: 'E',
replace: true,
template : "<h1>sub1</h1>",
link: function($scope, element, attrs) {
$scope.soJSON={
"entityinfo": {
"entity": "Customer29Jan16",
"tenantId": "292FEC76-5F1C-486F-85A5-09D88096F098",
"timeStamp": "2016-04-07T10:33:38.507Z"
},
"collections": {
"Customer29Jan16": {
"meta": {
"parentreference": "***",
"pkname": "***",
"fkname": "***"
},
"rowset": [
{
"CuId": "test",
"Name": "test",
"Quantity": "test"
}
],
"rowfilter": []
}
}
}
}
};
});
app.directive("sub2", function() {
return {
template : "<input ng-model=CuId> <input ng-model=Name> <input ng-model=Quantity>"
};
});
HTML Code:
<div ng-app="myApp">
<main>
<sub1>Test<</sub1>
<sub2>Test<</sub2>
</main>
</div>
JS Fiddle Link : https://jsfiddle.net/bagya1985/23vz1xux/1/
Well AngularJS supports directive controllers, which are controllers that are shared between multiple directives that require the same controller.you would need to use require:'^main' in your child directives . for more information you can check out the link https://docs.angularjs.org/guide/directive

AngularJS: route to /page/:id and show id's information?

I know it's a poorly constructed question, but I don't know how else to ask it.
I'm new to AngularJS, I'm trying to basically say "if a user clicks on "this" profile, go to /models/{{ model.id }} with model.id being the value of "this" profile that was clicked.
Basically, the main.html has only a bit of the information (a snippet, if you will), and when a profile is clicked it should go to /models/{{ model.id }} and then show the full profile as opposed to just a snippet.
I have it working so far in that the correct id shows up when hovering the profile link and it goes to the correct view with the correct url parameters, but how can I write data in the view that it goes to such that the data will be relevant to the ID that was clicked? I normally do this with PHP/Laravel and MySQL but I wanted to try it with Angular.
app.js:
'use strict';
angular
.module('swoleincApp', [
'ngRoute',
'ngSanitize',
'ngAnimate'
])
.config(['$routeProvider', '$locationProvider',
function($routeProvider, $locationProvider) {
$routeProvider
.when('/models', {
templateUrl: 'views/main.html',
controller: 'MainCtrl'
})
.when('/models/:id', {
templateUrl: 'views/individual.html',
controller: 'MainCtrl'
})
.otherwise({
redirectTo: '/models'
});
$locationProvider.html5Mode(true);
}]);
MainCtrl.js:
'use strict';
angular
.module('swoleincApp')
.controller('MainCtrl', ['$scope', '$http', MainCtrl]);
function MainCtrl($scope, $http) {
$http.get('storage/models.json').success(function(data) {
$scope.models = data;
});
}
main.html:
<div class="model-container" ng-repeat="model in models">
<a href="/models/{{ model.id }}">
<div class="row">
<div class="col-sm-2">
<div class="model-profile-image">
<img ng-src="{{ model.profileImage }}" width="100" height="100">
</div>
</div>
<div class="col-sm-8">
<div class="model-stats">
<h3>{{ model.name }}, {{ model.age }}, {{ model.height }}, {{ model.weight }}.</h3>
</div>
<div class="model-motto">
<p>{{ model.motto }}</p>
</div>
</div>
</div>
</a>
</div>
models.json (pretend the "other stuff" is meant for the individual profiles):
{
"1": {
"id": "1",
"profileImage": "../img/dom.jpg",
"name": "Dom",
"age": "19",
"height": "6'2",
"weight": "170lbs",
"motto": "My name is dom and I'm a 19 year old bodybuilder from Russia.",
"other": "other stuff",
"other": "other stuff",
"other": "other stuff",
"other": "other stuff",
},
"2": {
"id": "2",
"profileImage": "../img/Tom.jpg",
"name": "Tom",
"age": "21",
"height": "5'8",
"weight": "190lbs",
"motto": "I'm Tom. Everyone knows my name. Everyone knows my game.",
"other": "other stuff",
"other": "other stuff",
"other": "other stuff",
"other": "other stuff",
}
}
Use a different controller to simplify this. The parameter :id can be accessed using $routeParams injected into controller.
angular
.module('swoleincApp')
.controller('ProfileCtrl', ['$scope', '$http','$routeParams', ProfileCtrl]);
function ProfileCtrl($scope, $http, $routeParams) {
$http.get('storage/models.json').success(function(data) {
$scope.profile= data[$routeParams.id];
});
}
Be sure to update your routing config for this controller.
Normally you would create a service to handle retrieving the data and storing it. Have left $http in for now to keep it simple.
Suggest going through the phoneCat tutorial on documentations site.
Here's link to the routing section
All you need to do is to use the $RouteParams service. Here's the documentation on the AngularJS official website

Using non-angular external js functions inside angularjs controller

I'm still new to angularJs.
I need to access Enumerable class from linqjs inside an angularjs controller.
My ngController looks similar to this:
var app1= angular.module("app1");
app1.controller("peopleController", ['$scope', 'Restangular',
function($scope, Restangular) {
$scope.people = Restangular.all('people').getList()
$scope.selectedItem = Enumerable.From(people).FirstOrDefault(); // ERROR
}]);
The error I'm getting is:
ReferenceError: Enumerable is not defined
any help?
I think it should be:
var app1 = angular.module("app1");
app1.controller("peopleController", ['$scope', 'Restangular', function ($scope, Restangular) {
$scope.people = Restangular.all('people').getList();
$scope.selectedItem = Enumerable.From(people).FirstOrDefault(); // ERROR
}]);
So without the 'peopleController' name of the function.
Edit
The problem is that Enumerable ( which is defined in linqjs ) is not available at the moment that it is called. Therefore the injector is looking for it and for the Enumerableprovider, but it doesn't exist nor is it injected.
You want to make sure you load the linqjs sources before your application is run. If Enumerable is defined in the global scope, you should be fine to use it from your controller. I created a JsFiddle that loads angular and linqjs from a CDN and shows you that it will 'just work' from your controller: http://jsfiddle.net/ngn3Lprx/2/
var app = angular.module('myapp', []);
app.controller('myctrl', ['$scope', function ($scope) {
// Example from: http://linqjs.codeplex.com/
var jsonArray = [
{ "user": { "id": 100, "screen_name": "d_linq" }, "text": "to objects" },
{ "user": { "id": 130, "screen_name": "c_bill" }, "text": "g" },
{ "user": { "id": 155, "screen_name": "b_mskk" }, "text": "kabushiki kaisha" },
{ "user": { "id": 301, "screen_name": "a_xbox" }, "text": "halo reach" }
]
// ["b_mskk:kabushiki kaisha", "c_bill:g", "d_linq:to objects"]
$scope.queryResult = Enumerable.From(jsonArray)
.Where(function (x) { return x.user.id < 200 })
.OrderBy(function (x) { return x.user.screen_name })
.Select(function (x) { return x.user.screen_name + ':' + x.text })
.ToArray();
}]);
With view:
<div ng-app="myapp">
<div ng-controller="myctrl">
<pre>
{{ queryResult | json }}
</pre>
</div>
</div>
Gives:
[
"b_mskk:kabushiki kaisha",
"c_bill:g",
"d_linq:to objects"
]
As expected.
p.s. Dont' forget the semi-colon after .getList();

Categories