Access AngularJS expression with ng-click - javascript

I am having trouble to access angularjs expressions after the click event.
index.html
<div class="row">
<a href="#/company"><div class="tile col col-comp cat-a-g grow-appear" ng-click="onSelect(item)" ng-repeat="item in data" >
<p>{{item.compname}}</p>
</div></a>
</div>
The above code populate a list of company names. When I click on a company it opens company.html
company.html
<div class="comp-info col s12 grow-appear">
<span class="comp-logo-container">
<img src="images/aap3-160x70-black.jpg" />
</span>
<span class="comp-info-container">
<p><i class="far fa-envelope"></i>{{item.compemail}}</p>
<p><i class="fas fa-location-arrow"></i>{{item.compbuilding}}</p>
<p><i class="fas fa-phone"></i>{{item.compphone}}</p>
</span>
</div>
Controller (app.js)
$scope.onSelect = function($event, data) {
console.log(data);
}
File Structure
root
+--public
+--templates
+--company.html
+--index.html
+--javascript
+--app.js
+--views
+main.html
I am using ngRoute to inject index.html and company.html into main.html.
app.config(function($routeProvider){
$routeProvider
.when ('/', {
templateUrl: 'templates/home.html',
controller: 'AppCtrl'
})
.when ('/company', {
templateUrl: 'templates/company.html',
controller: 'AppCtrl'
})
});
So when I console.log() the controller, it shows the array of data but it doesn't add it to the company html document. What am I missing?

The structure of your application is a little unclear, but I think your problem may be to do with $scope. item in item in data is not accessible from the root of $scope. You can do something like this:
<div class="comp-info col s12 grow-appear">
<span class="comp-logo-container">
<img src="images/aap3-160x70-black.jpg" />
</span>
<span class="comp-info-container">
<p><i class="far fa-envelope"></i>{{selected.compemail}}</p>
<p><i class="fas fa-location-arrow"></i>{{selected.compbuilding}}
</p>
<p><i class="fas fa-phone"></i>{{selected.compphone}}</p>
</span>
</div>
Then:
$scope.onSelect = function($event, data) {
$scope.selected = data;
}

Related

Routing Angular JS Not Working and not throwing error

I tried to use $routeProvider. But something wrong and i dont know what. Console not throwing error and nothing happen in my page. Im confused. Any solution for me ?
This my code :
var app = angular.module("admin-rv-app", ['ngRoute']);
app.config(function($routeProvider) {
$routeProvider
// route for the home page
.when('/', {
templateUrl : 'templates/home.html',
controller : 'homeController'
})
// route for the thread page
.when('/thread', {
templateUrl : 'templates/thread.html',
controller : 'threadController'
});
});
app.controller('homeController', function($scope) {
$scope.message = "Welcome Home";
});
app.controller('threadController', function($scope) {
$scope.message = "Welcome to Thread";
});
This is my HTML
<li>
<a href="#">
<i class="fa fa-home fa-3x" aria-hidden="true"></i>
<span class="title">Home</span>
<span class="selected"></span>
</a>
</li>
<li>
<a href="#thread">
<i class="fa fa-briefcase fa-3x" aria-hidden="true"></i>
<span class="title">Thread + Answer</span>
<span class="selected"></span>
</a>
</li>
By the way I have include angular.min.js and angular.route.min.js and ng-app="admin-rv-app"
I think the problem is how you create your app.config.
app.config(["$routeProvider", function($routeProvider){
$routeProvider.when('/', {
templateUrl : 'templates/home.html',
controller : 'homeController'
})
// route for the thread page
.when('/thread', {
templateUrl : 'templates/thread.html',
controller : 'threadController'
});
}])
Try this out instead, and dont add $scope to the module, that will only give you more errors to handle.
Also change the tag, to "/thread" instead of #.
You need to use $routeProvider for the .when statement, otherwise angular cant user the $routeProvider for your diffrent views
Inject $location service in your controller
after that
<a ng-click="changeLocation()"/>
and
$scope.changeLocation = function (){
$location.path('/thread')
}
try using this in HTML:
<li>
<a href="#home">
<i class="fa fa-home fa-3x" aria-hidden="true"></i>
<span class="title">Home</span>
<span class="selected"></span>
</a>
</li>
<li>
<a href="#thread">
<i class="fa fa-briefcase fa-3x" aria-hidden="true"></i>
<span class="title">Thread + Answer</span>
<span class="selected"></span>
</a>
</li>
And change the router code to this:
app.config(function($routeProvider) {
$routeProvider
// route for the home page
.when('/home', {
templateUrl: 'app/dashboard/home.html',
controller: 'homeController'
})
// route for the thread page
.when('/thread', {
templateUrl : 'templates/thread.html',
controller : 'threadController'
});
});
If you notice I have changed the URL from "/" to "/home"
and I checked, it is working. Let me if it's not working at your end

Can't show single item on click Angular

I'm getting the following error when I want to click on a link to show a single template (item):
WARNING: Tried to load angular more than once.
Link to screenshot: http://i.imgur.com/ZZDEA3J.png
Here is my templates.html code:
<div ng-repeat="template in filteredTemplates | filter:q" class="col-lg-4 col-md-6 col-sm-6 col-xs-12 portfolio-item">
<h4>
<a href="/edit/{{template.id}}" class="template-name" >{{ template.name }} </a>
</h4>
<p>{{ template.content.substring(0, 40) | htmlToPlaintext | removeNbsp }} ...</p>
<div class="row">
<div class="col-lg-6">
<div ng-repeat="license in template.licenses">{{license.name}} prijs <i class="fa fa-eur" aria-hidden="true"></i> {{license | setPrice}}</div>
</div>
<div class="col-lg-6">
<a ng-click="placeOrder(template)" class="btn btn-info" role="button"> Add to cart <span class="fa fa-cart-plus"></span></a>
</div>
</div>
</div>
app.js code:
//This will handle all of our routing
app.config(function($routeProvider, $locationProvider){
$routeProvider.when('/', {
templateUrl: 'js/templates/home.html',
controller: 'HomeController'
});
$routeProvider.when('/templates', {
templateUrl: 'js/store/templates.html',
controller: 'TemplateController'
});
$routeProvider.when('/edit/:id', {
templateUrl: 'js/store/template.html',
controller: 'GetTemplateController'
});
$locationProvider.html5Mode({
enabled: true,
requireBase: false
});
});
templateController.js:
template.controller('GetTemplateController', function ($scope, $routeParams, Template) {
console.log('here');
});
I suspect that the problem comes from the app.js file. Does someone knows what I'm doing wrong? Because I really can't figure it out
Taken from here:
You'll notice that if the app can't find a file (i.e., otherwise), then it will redirect to the root, which in this case loads the templateUrl. But if your templateUrl is wrong, then it will cause a recursion that reloads index.html loading angular (and everything else) over and over.
Seems like wrong template url is what's causing this.

Directive to externalize view not working

I'm using pageslide directive in order to display a lateral sliding menu when I click on an icon.
This is the usual way to do it, and its working :
<div class="navbar-header">
<span ng-controller="slideController as s">
<a class="navbar-brand" href="javascript:void(0)"
ng-click="s.toggle()"><i class="fa fa-bars fa-lg"></i></a>
<div pageslide ps-open="s.isActive" ps-side="left">
<div style="padding:20px">
<h2>Hello Pageslide</h2>
<p>Put here whatever I want in the lateral menu</p>
<a ng-click="s.toggle()" class="button" >Close</a>
</div>
</div>
</span>
<a class="navbar-brand text-danger" href="javascript:void(0)">Balrog</a>
</div>
But I would lilke to make the menu content in an external template, so I'm trying this :
<div class="navbar-header">
<span ng-controller="slideController as s">
<a class="navbar-brand" href="javascript:void(0)"
ng-click="s.toggle()"><i class="fa fa-bars fa-lg"></i></a>
<menu-item isActive="s.isActive"></menu-item>
</span>
<a class="navbar-brand text-danger" href="javascript:void(0)">Balrog</a>
</div>
with this as menu.html :
<div pageslide ps-open="s.isActive" ps-side="left">
<div style="padding:20px">
<h2>Hello Pageslide</h2>
<p>Put here whatever I want in the lateral menu</p>
<a ng-click="s.toggle()" class="button" >Close</a>
</div>
</div>
also, here is the related controller :
'use strict';
angular.module('BalrogApp').controller('slideController', function(){
this.isActive= false; // This will be binded using the ps-open attribute
this.toggle = function(){
this.isActive= !this.isActive
}
});
and the <menu-item> directive :
angular.module('BalrogApp').directive('menuItem', function () {
return {
restrict: 'E',
templateUrl: "views/menu.html",
scope: {
isActive: '='
},
controller: 'slideController',
controllerAs: 's',
bindToController: true
}
});
So it's not working this way, maybe it is because the main view (including the <menu-item>) is itself included in the main page thanks to <ng-view> ?
Or maybe the pageslide-directive requires the <div pageslide ...> and its parent element to be on the same file ?
I can tell from the console that toggle() is called and changes isActive in both cases but it's not opening the menu with the directive version.
And also, adding ng-controller="slideController as s" to the root <div> with the pageslide attribute didn't change anything.
So how can I make this work with the menu in another file ?
Did you try to replace <div ng-include="menu.html"></div> with <div ng-include="'menu.html'"></div>. According to https://docs.angularjs.org/api/ng/directive/ngInclude, you have to wrap string constants in single quotes.
I highly recommend you not use ng-include. You can get the same approach using directive instead.
For example:
Menu html
<div pageslide ps-open="vm.checked" ps-side="left">
<div style="padding:20px">
<h2>Hello Pageslide</h2>
<p>Put here whatever I want in the lateral menu</p>
<a ng-click="vm.toggle()" class="button" >Close</a>
</div>
</div>
Directive:
function Controller() {
}
Controller.prototype.toggle = function() {
this.checked = !this.checked;
}
angular
.module('BalrogApp')
.directive('menuItem', function() {
return {
templateUrl: 'urltomenu.html',
restrict: 'E',
scope: {
checked: '='
},
controller: Controller,
controllerAs: 'vm',
bindToController: true
}
})
Main template
<div class="navbar-header">
<span ng-controller="slideController as s">
<a class="navbar-brand" href="javascript:void(0)"
ng-click="s.toggle()"><i class="fa fa-bars fa-lg"></i></a>
<menu-item checked="s.checked"><menu-item>
</span>
<a class="navbar-brand text-danger" href="javascript:void(0)">Balrog</a>
</div>
This approach give you more power. All the logic is inside the directive controller and you could reuse this element each time. The scope attribute checked is the "bridge" between your main template if change outside also change inside and also the other way.

AngularJS routing multiple ui-views for the same URL?

I need multiple ui-views for one URL (my homepage). The limitation for ui-routing is that I can't have multiple <div ui-view></div> but they have to be in their nested states.
<div class="left-div">
<div ui-view></div>
<button ui-sref="1"></button>
<button ui-sref="2"></button>
<button ui-sref="3"></button>
</div>
<div class="right-div">
<button ui-sref="3"></button>
<div ui-view></div>
</div>
How do I make it so that ui-sref=1 and ui-sref=2 will update the ui-view inside:
<div class="left-div"></div>
and ui-sref=3 will update the ui-view inside <div class="right-div"></div>
The issue I encountered when I used ui-router was that upon changes from ui-sref from 1 -> 3 or 2 -> 3 the ui-view of left-div will disappear because the URL changes.
How do I approach this?
EDIT- My current state views
chatApp.config(function($stateProvider, $urlRouterProvider) {
$urlRouterProvider.otherwise('/home')
$stateProvider
.state('friend', {
url: '/friend',
templateUrl: 'friend.html'
})
.state('group', {
url: '/group',
templateUrl: 'group.html'
})
.state('search', {
url: '/search',
templateUrl: 'search.html'
})
.state('home', {
url: '/search',
templateUrl: 'search.html'
})
.state('public', {
url: '/public',
views: {
'publicView': { templateUrl: 'private-chat.html' }
}
});
<div class="col-md-3 left-col-friends" ng-controller="friendListCtrl">
<div class="friends-list-navigation">
<div class="option-wrapper">
<div class="col-xs-3 home-option" ui-sref="public"><i class="fa fa-home fa-2x"></i></div>
<div class="col-xs-3 friend-option" ui-sref="friend"><i class="fa fa-user fa-2x"></i></div>
<div class="col-xs-3 group-option" ui-sref="group"><i class="fa fa-users fa-2x"></i></div>
<div class="col-xs-3 search-option" ui-sref="search"><i class="fa fa-search fa-2x"></i></div>
</div>
</div>
<div class="friends-list-display">
<div ui-view></div>
</div>
</div>
<div class="col-md-9 middle-col-chat" ng-controller="publicCtrl">
<div class="bubble-frame-public">
<div ui-view="publicView"></div>
</div>
<div class="input-fields-wrapper" emoji-form emoji-message="emojiMessage">
<div class="col-md-8">
<textarea class="col-md-4" id="messageInput" ng-model="emojiMessage.messagetext"></textarea>
</div>
<div class="col-md-3">
<button class="btn btn-default btn-send-public-msg" ng-click="emojiMessage.replyToUser()"><i class="fa fa-paper-plane"></i></button>
<button class="btn btn-default" id="emojibtn">
<i class="fa fa-smile-o"></i>
</button>
<button class="btn btn-default"><i class="fa fa-video-camera"></i></button>
</div>
</div>
</div>
I'm taking a guess that the publicView is the view you're wanting to stay unchanged while the other views are changing. Here's one way to tackle it.
$stateProvider
.state('home', {
url: '/home',
views: {
'#': {
templateUrl: 'search.html'
},
'publicView#': {
templateUrl: 'private-chat.html'
}
}
})
.state('home.friend', {
views: {
'#': {
templateUrl: 'friend.html'
}
}
})
.state('home.group', {
views: {
'#': {
templateUrl: 'group.html'
}
}
});
The default URL is /home. When it's accessed, publicView is populated with private-chat.html and the unnamed ui-view is populated with search.html.
For the friend and group states, they leave the publicView alone and they don't use new URLs, which is what I think you're going for. This is accomplished by making them children states of home and by specificying absolutely which views should be altered.

Angular/Rails get last saved data from table

I am new to AngularJS and I am trying to incorporate Angular into my already built Rails app. In my rails app have a the ability to post to a feed. I have Angular working so it retrieves the feed and also posts the latest record to the feed.
My issue is that it only post the contents of the form. I am looking to retrieve the user id as well so I can render out the user's name, profile pic, etc. This information shows up when I refresh the page but does not show right after the post happens, only the contents of the post shows.
microposts.js.coffee
app = angular.module('micropostApp', ['ui.router', 'ngResource'])
app.factory 'Micropost', ["$resource", ($resource) ->
return $resource('/')
]
app.factory 'createMicropost', ["$resource", ($resource) ->
return $resource('/microposts')
]
app.factory 'Comments', ["$resource", ($resource) ->
return $resource('/microposts/:id/comments', id: '#id')
]
app.controller 'MicropostsController', [
'$scope'
'Micropost'
'createMicropost'
'Comments'
($scope, Micropost, createMicropost, Comments) ->
Micropost.query (data) ->
$scope.microposts = data
$scope.addPost = ->
if !$scope.newPost or $scope.newPost == ''
return
post = createMicropost.save($scope.newPost)
console.log("POST: " + angular.toJson(post))
$scope.microposts.unshift(post)
$scope.newPost = {}
]
microposts controller
respond_to :json
def create
#micropost = current_user.microposts.create!(micropost_params)
respond_with #micropost
end
view
<div ng-app="micropostApp" ng-controller="MicropostsController">
<div class="row">
<div class="col-md-12">
<form ng-submit="addPost()" style="margin-top:30px;">
<div class="form-group">
<input type="textarea"
class="form-control"
placeholder="Post an update..."
ng-model="newPost.content"></input>
</div>
<button type="submit" class="btn btn-primary pull-right">Post</button>
</form>
</div>
</div>
<div ng-repeat="post in microposts">
<div class="row">
<div class="panel panel-default">
<div class="panel-body">
<li id="{{post.id}}">
<div class="row">
<div class="col-md-12">
<aside>
{{post.user.name}}
</aside>
<aside>
<li id="feed-fat-menu" class="dropdown pull-right feed-dropdown">
<a href="#" class="dropdown-toggle" data-toggle="dropdown">
<b class="glyphicon glyphicon-chevron-down"></b>
</a>
<ul class="dropdown-menu">
<li>Delete</li>
</ul>
</li>
<span class="user"> {{post.user.name}} </span>
<span class="content">{{post.content}}</span>
<hr>
<span class="timestamp pull-right"> Posted {{post.created_at}} ago. </span>
<span class="pull-left" style="padding-right: 5px;"><a>Comment </a>({{post.comments.length}})</span>
<span class="pull-left" style="padding-right: 5px;">
<a>Likes</a> ({{post.likes.length}})
</span>
<br />
</aside>
</div>
</div>
</li>
</div>
</div>
</div>
</div>
I'm not familiar with coffescript. If it's loading in the data on page reload, I would just add a call to whatever function is triggering that in the $scope.addPost call stack.
$scope.addPost = function(){
if(!$scope.newPost || $scope.newPost == ''){
return
}
post = createMicropost.save($scope.newPost);
console.log("POST: " + angular.toJson(post));
$scope.microposts.unshift(post);
$scope.newPost = {};
Micropost.get();
}
app.factory("Micropost", ["$resource", function($resource) {
return $resource("/", {}, {
get: {
method: "GET",
cache: true
}
});
}]);

Categories

Resources