Controller doesn't get parent data - angularjs

I'm doing a tutorial over angular 1.5 and I've gotten far into it and one of the sections seems broken concerning matching a current user to the author username. The class injects the User service and I think assumes I can inherit from a parent controller for the author but it comes up undefined. I tried injecting $scope then setting a variable to $scope.$parent.article (article is the object that has the author name in it) but this was still undefined. I checked the parent controller doing a console log on article and it does have the data that I am trying to get. Here is a link to my project if you want to look at the entire thing but I'll try to post just the relevant code below. https://github.com/RawleJuglal/flow_news_app/tree/front_end/src/js
Parent Controller (article.controller.js)
import marked from 'marked';
class ArticleCtrl {
constructor(article, $sce, $rootScope) {
'ngInject';
this.article = article;
console.log(this.article);
//THIS IS CONSOLE LOG
//{title: "Juglal For StackOverflow",
slug: "juglal-for-stackoverflow-ba400n",
body: "<p> Need the goods</p>",
createdAt: "2017-04-25T14:51:42.131Z",
updatedAt: "2017-04-25T14:51:42.131Z",
author:{
bio:"I'm a MEAN stack developer. But if I don't find a job in Oklahoma soon, I'll be learning C++/Sharp."
following:false
image:"https://media.licdn.com/mpr/mpr/shrinknp_200_200/p/6/000/1e9/0e2/3cd7175.jpg"
username:"RawleJuglal",....
}
// Update the title of this page
$rootScope.setPageTitle(this.article.title);
this.article.body = $sce.trustAsHtml(marked(this.article.body, { sanitize: true }));
}
}
export default ArticleCtrl;
Child Controller (article-actions.components.js)
class ArticleActionsCtrl {
constructor(Articles, User, $state) {
'ngInject';
this._Articles = Articles;
this._$state = $state;
//Code that causes the error because this.article.author.username is undefined
if (User.current) {
this.canModify = (User.current.username === this.article.author.username);
} else {
this.canModify = false;
}
}
}
let ArticleActions = {
bindings: {
article: '='
},
controller: ArticleActionsCtrl,
templateUrl: 'article/article-actions.html'
};
export default ArticleActions;
HTML(article.html) //Just in case this the problem
<div class="article-page">
<div class="banner">
<div class="container">
<h1 ng-bind="::$ctrl.article.title"></h1>
<article-actions article="$ctrl.article"></article-actions>
</div>
</div>
<div class="container page">
<div class="row article-content">
<div class="col-xs-12">
<div>
<div ng-bind-html="::$ctrl.article.body"></div>
</div>
<ul class="tag-list">
<li class="tag-default tag-pill tag-outline"
ng-repeat="tag in ::$ctrl.article.tagList">
{{ tag }}
</li>
</ul>
</div>
</div>
<hr />
<div class="article-actions">
<article-actions article="$ctrl.article"></article-actions>
</div>
<div class="row">
<div class="col-xs-12 col-md-8 offset-md-2">
<div>
<form class="card comment-form">
<div class="card-block">
<textarea class="form-control"
placeholder="Write a comment..."
rows="3"></textarea>
</div>
<div class="card-footer">
<img class="comment-author-img" />
<button class="btn btn-sm btn-primary" type="submit">
Post Comment
</button>
</div>
</form>
</div>
<div class="card">
<div class="card-block">
<p class="card-text">This is an example comment.</p>
</div>
<div class="card-footer">
<a class="comment-author" href="">
<img class="comment-author-img" />
</a>
<a class="comment-author" href="">
BradGreen
</a>
<span class="date-posted">
Jan 20, 2016
</span>
</div>
</div>
</div>
</div>
</div>
</div>

In fact, your example will work with angular 1.5 but not >1.6.
here is the reason :
Starting with angular 1.6, bindings are not yet set in the constructor. If you need them, move your code to the $onInit function.
Here is your new ArticleActionsCtrl :
class ArticleActionsCtrl {
constructor(Articles, User, $state) {
'ngInject';
this._Articles = Articles;
this._$state = $state;
this.User = User;
}
$onInit() {
if (this.User.current) {
this.canModify = (this.User.current.username === this.article.author.username);
} else {
this.canModify = false;
}
}
}
let ArticleActions = {
bindings: {
article: '='
},
controller: ArticleActionsCtrl,
templateUrl: 'article/article-actions.html'
};
export default ArticleActions;
I did not test it, do not hesitate to tell me if you have any problem with it.

Related

angularjs ng-model not binding after state change

There are three states defined in my project called "/projects","/pages" and "/settings". The function given below works without any problem in case not state changing (I also tried with ngRoute but the result was same). But when I started to change states and then get back to the same page this function not binding data to the modal box. [There is no error occurred in this situation!] (when I'm refreshing page it turns back to normal).
My app.js file
// Dependencies wired beforehand.
/** #var {Object} projects Page management page state */
var projects = {
name: 'projects',
url: '/projects',
templateUrl: TEMPLATES_DIR + 'projects.html',
controller: 'projects'
};
/** #var {Object} pages Page management page state */
var pages = {
name: 'pages',
url: '/pages',
templateUrl: TEMPLATES_DIR + 'pages.html',
controller: 'pages'
};
/** #var {Object} settings Settings page state */
var settings = {
name: 'settings',
url: '/settings',
templateUrl: TEMPLATES_DIR + 'settings.html',
controller: 'settings'
};
$stateProvider.state(projects);
$stateProvider.state(pages);
$stateProvider.state(settings);
Function from projects controller: (This function binds data to modal box)
$scope.getProjectImages = function(id) {
$scope.projectId = id;
projectsFactory.getImages(id).then(function(response) {
$scope.images = response.data;
//I can see that it's holding array but it's not binding data to modal box anymore when the state changed
alert($scope.images);
});
};
template file (UPDATED):
<div id="project-image-manager" class="uk-modal-container uk-position-z-index" uk-modal="stack: true; bg-close: false; container: false">
<div class="uk-modal-dialog uk-modal-body">
<button class="uk-modal-close-default" type="button" ng-click="resetProjectImagesModal()" uk-close></button>
<div class="uk-grid-divider" uk-grid>
<div class="uk-animation-slide-bottom-medium uk-width-1-3#m uk-margin-medium-top">
<h3>Image Attachment<span class="uk-display-block uk-text-small">File Management</span></h3>
<form method="post" enctype="multipart/form-data">
<button ngf-select="uploadImage($files)" class="uk-button uk-margin-bottom uk-button-default uk-text-capitalize uk-text-left" accept="image/*" multiple>Upload Images<span class="uk-icon uk-margin-small-left" uk-icon="icon: image"></span></button>
</form>
<p>{{ errorMsg }}</p>
<progress class="uk-progress" value="{{ progress }}" max="100"></progress>
<ul class="uk-list uk-text-small uk-margin-large-top uk-list-divider">
<li ng-repeat="file in files">{{ file.name }}</li>
</ul>
</div>
<div class="uk-width-expand#m">
<div class="uk-background-default uk-padding-bottom uk-width-expand uk-text-center" ng-if="images.length">
<p class="uk-animation-slide-left-small" ng-if="sortableImages.disabled">
<span class="uk-icon uk-margin-small-right" uk-icon="icon: lock"></span><a class="uk-text-muted uk-link-reset" ng-click="sortableImages.disabled = false">Unlock to sort images</a>
</p>
<p class="uk-animation-slide-left-small" ng-if="!sortableImages.disabled">
<span class="uk-icon uk-margin-small-right" uk-icon="icon: unlock"></span><a class="uk-text-muted uk-link-reset" ng-click="sortableImages.disabled = true">Lock sorting</a>
</p>
</div>
<h3 class="uk-animation-fade uk-text-center uk-text-muted uk-margin-large-top uk-align-center" ng-show="!images.length">
<span class="uk-icon uk-display-block" uk-icon="icon: image; ratio: 4"></span>This project has no images.
</h3>
<div ng-if="images.length">
<ul class="uk-animation-fade uk-list uk-margin-medium-top" ng-model="images" ui-sortable="sortableImages">
<li class="uk-margin-medium-bottom" ng-model="images" ng-repeat="image in images">
<div uk-grid>
<div class="uk-width-1-2#m uk-width-1-3#s mobile-width-image sortable-image-item">
<div class="uk-background-cover uk-width-1-4#xs uk-panel uk-flex uk-flex-center uk-flex-middle image-thumbnail-height" style="background-image: url({{ uploadPath }}{{ image.url }});">
</div>
</div>
<div class="uk-width-1-2#m uk-width-2-3#s mobile-width-text">
<p class="uk-text-muted" ng-if="!image.description.length">No description given.</p>
<p>{{ image.description }}</p>
<hr class="uk-divider-small uk-margin-top uk-margin-bottom">
<ul class="uk-iconnav uk-padding-remove-left">
<li>
<a ng-click="getImageDescription(image.id)" uk-icon="icon: file-edit" uk-toggle="target: #add-description"></a>
</li>
<li>
<a ng-click="removeImage(image)" uk-icon="icon: trash"></a>
</li>
</ul>
</div>
</div>
</li>
</ul>
</div>
</div>
</div>
</div>
</div>
What's wrong with that code? My last plan giving up doing in SPA and go with traditional routing. :D Thanks for your help.
I solved out. DOM appended container option for modal box prevents data binding. It's UIkit CSS Framework related problem.
Solution: Set container option to false.
Here is the solution:
uk-modal="...other options.. container: false">
UIkit js reference:
container String true Define a target container via a selector to specify where the modal should be appended in the DOM. Setting it to false will prevent this behavior.

Update view when api get data in Angularjs

So, i have a little problem. I made a tiny webapp that uses the omdb api. The thing is this that when i type in the movie that i'm searching for then press the search button, the view should change to the result.html view and show the data i got from the api.
The api works fine. I got the data to display, but that was in my index.html. Now i have splitted the files by using ng-routes
I can provide you the whole project if you wanna look at it. Maybe i can upload it to a online editor somewhere?
This is my app.js
var myApp = angular.module("myApp", ['ngRoute']);
myApp.config(['$routeProvider', function ($routeProvider) {
$routeProvider.
when('/home', {
templateUrl: 'views/home.html',
controller: 'filmController'
}).
when('/result', {
templateUrl: 'views/result.html',
controller: 'filmController'
}).otherwise({
redirectTo: '/home'
})
}]);
myApp.controller("filmController", function filmController($scope, $http, $window) {
$scope.getData = function () {
var movieTitle = document.getElementById("filmName").value;
var binding = document.getElementsByClassName("ng-binding");
$http
.get("http://www.omdbapi.com/?t=" + movieTitle + "&apikey=526345a6")
.then(function (response) {
var data = response.data;
if (data.Error) {
alert("Film inte funnen");
return false;
}
for (let key in data) {
if (data.hasOwnProperty(key)) {
let element = data[key];
if (element === "N/A") {
data[key] = "Inget hittat";
if (key === "Poster") {
$scope.post = "Ingen poster hittad";
}
}
$scope.url = data;
}
}
if (data.Ratings.length === 0) {
$scope.rate = "Ingen utmärkelse/er hittad";
}
// This api data is printed to the console on the index.html view, i want it in the result view...
console.log(data);
});
};
});
This is my index.html
<body>
<div class="main-content">
<!-- <div class="container">
<div class="row">
<div ng-controller="MyController">
<div ng-repeat="item in larare" class="col-lg-12">
<div class="card">
<img ng-src="/images/{{item.shortname}}.jpg" alt="Bild på {{item.name}}" class="card-img-top">
<div class="card-body">
<h3 class="card-title">{{item.name}}</h3>
<p class="card-text">{{item.reknown}}</p>
</div>
</div>
</div>
</div>
</div>
</div>
</div> -->
<header ng-include="'header.html'"></header>
<main ng-view></main>
</div>
</div>
<script>
var elem = document.getElementsByTagName("body")[0];
if (elem.requestFullscreen) {
elem.requestFullscreen();
console.log("Nu");
} else {
console.log("Error");
}
function updateSite(event) {
window.applicationCache.swapCache();
}
window.applicationCache.addEventListener('updateready',
updateSite, false);
</script>
<script src="./js/formvalidation.js"></script>
</body>
</htm>
And my result view
<div class="show container" ng-show="url.Title">
<div class="poster">
<!-- <img ng-src="{{ url.Poster }}" alt="" /> -->
<img ng-src="{{ url.Poster == 'Inget hittat' ? './images/image_not_found.png' : url.Poster }}">
<p class="text-dark">{{ post }}</p>
</div>
<h2 class="text-dark">{{ url.Title | uppercase}}</h2>
<div class="movie-info">
<p class="text-dark">
<strong>Från:</strong> {{ url.Year }}</p>
<p class="text-dark">
<strong>Rating:</strong> {{ url.Rated }}</p>
<p class="text-dark">
<strong>Utgiven:</strong> {{ url.Released }}</p>
<p class="text-dark">
<strong>Längd:</strong> {{ url.Runtime }}</p>
</div>
<p class="text-dark">
<strong>Skådespelare:</strong> {{ url.Actors }}</p>
<p class="text-dark">
<strong>Regissör:</strong> {{ url.Director }}</p>
<p class="text-dark">
<strong>Utmärkelser:</strong> {{ url.Awards }}</p>
<p class="text-dark">
<strong>Handling: </strong> {{ url.Plot }}</p>
<h4 class="text-dark">
<strong>Utmärkelser</strong>
</h4>
<p class="text-dark ">{{ rate }}</p>
<div ng-repeat="rating in url.Ratings | orderBy: '-Value'">
<p class="text-dark">
<strong>{{ rating.Source + ': ' + rating.Value }}</strong>
</p>
</div>
This is my home view
<section class="text-white">
<img src="./images/background.jpg" alt="Bild på poster från Frankenstein filmen" class="bg-image">
<div class="main container align-middle">
<div class="row text-center justify-content-center section-intro">
<div class="col-6 mb-5">
<h1>Filmtipset</h1>
<h5>Sök efter dina favortfilmer</h5>
</div>
</div>
<form ng-submit="getData()">
<div class="inputSearch mx-auto">
<div class="row justify-content-center">
<div class="col-8">
<div class="form-group">
<label for="filmName">Film</label>
<input class="form-control" type="text" name="filmName" id="filmName" placeholder="Ex. Armageddon" autofocus>
</div>
<input type="submit" class="btn btn-primary btn-lg btn-block btn-info mt-5" onclick="validateForm()" ng-click="'#!/result'">
</div>
</div>
</form>
Just a few notes before we break down the issue you are seeing. It seems like you aren't using angularjs to its full potential. Using a mixture of jquery and angularjs is not best practice and can make debugging very difficult. I would recommend making movieTitle an ng-model, as well as using angularjs's built in form validation. This will allow you to access the movieTitle easily in your controller as well as take advantage of angular's built in form controller and actions.
As for getting the data to your other page, I would add a second controller for that page, then from your filmController, you can pass the movie title as a route param when changing views. In your resultController, you can get the movie title from the route param and then do your api call while initializing the result page/controller.
In your home.html file, we will add ng-model to the input to be more angularjs friendly. Now we can access movieTitle in the controller with $scope.movieTitle. I am also changing the method that should get run on submit to the search() method I have added to the filmController.
home.html
<form ng-submit="search()">
// ... your other html here
<input class="form-control" type="text" name="filmName" id="filmName" ng-model="movieTitle" placeholder="Ex. Armageddon" autofocus>
In your filmController, I would add $location and move the getData() method to a resultController. We will now call search() on form submit, then use $location to switch views to your result view, attaching the movie title as a route param so we can access it in the resultController.
filmController.js
myApp.controller("filmController", function filmController($scope, $http, $location) {
// ... other code you have
// this will be what gets called after the user types a movie title
$scope.search = function () {
var title = $scope.movieTitle; // or using jquery(not recommended)
// this will change location and will produce
// the url: http://[yoursite]/result?movieTitle=title
$location.path('/result').search({movieTitle: title});
}
});
In your newly created resultController, we will get that route param and use it to search for the data.
resultController.js
myApp.controller("resultController", function resultController($scope, $http, $routeParams) {
// the getData method moved to this controller
$scope.getData = function (movieTitle) {
$http
.get("http://www.omdbapi.com/?t=" + movieTitle + "&apikey=526345a6")
// the rest of your code for getData here
};
// I like to make an init method to make it clear what we are initializing
$scope.init = function () {
// this will get the movieTitle from the /result?movieTitle=title part of your url
var movieTitle = $routeParams['movieTitle'];
// now we call the method you have that uses the omdb api
// just modify it to accept the movie title as a param rather than finding it in the html
$scope.getData(movieTitle);
}
// run init method
$scope.init();
});
Finally, you will want to update your app config to have your result route use the resultController we added instead of the filmController.

Separation components and codereview in AngularJS

I started read about modules, components, directives. I would like to ask you to check the code and say how I could improve it. The main thing for me is to figure out how I can improve the transparency of this code. I would also like to learn how to split this code into files, and how it should look like the file structure in this case. I heard that I should make one file for components, But how should it look in the inside?
I would really be grateful for help.
because the most important in the life of the programmer is the code review! :)
(function () {
angular.module('app.navbar', [])
.component('navbar', {
bindings: {
user: '<'
},
controller: function ($scope) {
var navbar = this;
this.$onInit = function () {
navbar.toggle = false;
};
this.activeMenu = function (name, $event) {
this.blockClosingList($event);
if (navbar.toggle === true && $scope.name == name) {
navbar.toggle = !navbar.toggle;
}
else if (navbar.toggle === false) {
navbar.toggle = !navbar.toggle;
}
$scope.name = name;
}
this.blockClosingList = function ($event) {
$event.stopPropagation();
}
},
controllerAs: 'navbar',
template: `
/////// MENU LEFT SIDE ///////
<div class="main-navbar">
<div class="menu-left">
<div class="btns">
<span class="glyphicon glyphicon-align-left btn__glyph"></span>
<span class="btn--name">Tablice</span>
</div>
<div class="btns navbar__search">
<span class="glyphicon glyphicon-search"></span>
</div>
</div>
<div class="navbar__logo">
<span class="navbar--logo">Tasker</span>
</div>
/////// MENU RIGHT SIDE ///////
<div class="menu-right">
<a href="#" ng-click="navbar.activeMenu('Create', $event);">
<div class="btns">
<span class="glyphicon glyphicon-plus"></span>
</div>
</a>
<!-- MENU CREATE -->
<div class="menu menu--create" ng-click="navbar.blockClosingList($event)" ng-class="{active : name === 'Create' && navbar.toggle === true}">
<!--close-->
<menu-create></menu-create>
</div>
<!---->
<!--MENU CREATE BOARD-->
<div class="menu cb__menu-coordinate menu--create-board" ng-click="navbar.blockClosingList($event)" ng-class="{active : name === 'menuCreateBoard' && navbar.toggle === true}">
<span class="settings-menu__header-title">Utwórz Tablicę</span>
<div class="menu__wrapper--create-board center-block">
<menu-create-board></menu-create-board>
</div>
</div>
<!---->
<a href="#" ng-click="navbar.activeMenu('Notice', $event);">
<div class="btns">
<span class="glyphicon glyphicon-bell"></span>
</div>
</a>
<!--NOTIFICATIONS-->
<div class="menu menu--notice" ng-click="navbar.blockClosingList($event)" ng-class="{active : name === 'Notice' && navbar.toggle === true}">
<notifications></notifications>
</div>
<!---->
<a href="#" ng-click="navbar.activeMenu('Profile', $event);">
<div class="btn__circle">
<span class="btn--circle">B</span>
</div>
</a>
<!--MENU PROFILE -->
<div class="menu menu--avatar" ng-click="navbar.blockClosingList($event)" ng-class="{active : name === 'Profile' && navbar.toggle === true}">
<profile-menu></profile-menu>
</div>
</div>
</div>
<!---->
`
})
.component('profileMenu', {
require: {
parent: '^navbar'
},
template: `
<!--close-->
<span class="settings-menu__header-title">
{{$ctrl.parent.user.username}} {{$ctrl.parent.user.role}}
</span>
<ul class="menu__avatar--list">
<li>
Profil
</li>
<li>
<a href="/{{$ctrl.parent.user.username}}">
Karty</a>
</li>
<li>
<a href="/{{$ctrl.parent.user.username}}">
Ustawienia</a>
</li>
<li>
<a href="/logout">
Wyloguj</a>
</li>
</ul>
`
})
.component('notifications', {
require: {
parent: '^navbar'
},
template: `
<!--close-->
<span class="settings-menu__header-title">Powiadomienia</span>
<div class="menu__field--placeholder">
<span>Brak powiadomień</span>
</div>
`
})
.component('menuCreateBoard', {
require: {
parent: '^navbar'
},
template: `
<form>
<div class="form-group">
<label for="">Tytuł</label>
<input type="text" class="form-control">
</div>
<div class="form-group">
<label for="">Zespół</label>
<input type="text" class="form-control">
</div>
<span class="bottom--create-board">Ta tablica będzie Prywatna. Zmień</span>
<button class="btn btn-success">Utwórz</button>
</form>
`
})
.component('menuCreate', {
require: {
parent: '^navbar'
},
template: `
<span class="settings-menu__header-title">Utwórz</span>
<ul class="menu__create--list">
<li>
<a href="#" ng-click="$ctrl.parent.activeMenu('menuCreateBoard', $event);">
<div class="menu__wrapper-create">
<span class="menu-create__heading">Utwórz tablicę</span>
<span class="menu-create__desc">Tablica składa się z kart uporządkowanych w listach. Użyj jej do zarządzania projektami, śledzenia informacji i organizowania wszystkiego.</span>
</div>
</a>
</li>
<li>
<a href="#">
<div class="menu__wrapper-create">
<span class="menu-create__heading">Utwórz zespół</span>
<span class="menu-create__desc">Zespół składa się z ludzi i tablic. Organizuj z jego pomocą firmę, swoją drugą pracę, plany dla rodziny i spotkania z przyjaciółmi.</span>
</div>
</a>
</li>
</ul>
`
})
})();
https://gist.github.com/Turqus/2a791c6b86adfc8b6732711eaec2e23d
in main app:
var App = angular.module('TodoListApp', ['dndLists', 'app.navbar']);
First I would advise you to go here and learn how to use webpack:
https://webpack.github.io/
After you learn how to bundle your files, you should separate templates out of your js files and use templateUrl to load template - you can webpack template loader - works very good.
Then to improve it even further you can learn to use javascript export (https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/export) functionality and separate your code in files.
I like the following directory structure (for example you could use navbar instead of my-component-name):
/my-component-name - directory
my-component-name.component.js - contains my component bindings and templateUrls, also here we import controller for that particular component.
my-component-name.controller.js - sets up controller for component
my-component-name.html - template
my-component-name.scss/less - less/sass file containing isolated styles for that particular component - wrapped in my-component-name {...}
index.js - contains all code put together declaration of angular module, all imports (component,services, directives) and dependencies.
index.js example (you can name it navbar-module.js):
import NavbarComponent from './navbar.component'; // <- here you import component
const NavbarModule = angular
.module('navbar', [])
.component('navbar', NavbarComponent) // <- here you define your component
.name;
export default NavbarModule;
navbar.component.js example:
import templateUrl from './navbar.html';
import controller from './navbar.controller.js'
const NavbarComponent = {
bindings: {
user: '<'
},
templateUrl, // just a shorthand for writing templateUrl: templateUrl
controller, // same as above
}
export default NavbarComponent;
and finally navbar.controller.js:
class NavbarController {
constructor($scope, $timeout) {
this.$scope = $scope;
this.$timeout = $timeout;
}
$onInit() {
// set up your on init code here
this.toggle = true;
}
// set up your functions on controller - they will behave same and you will be able to access them via $ctrl.activeMenu() or $ctrl.blockClosingList() in your templates
activeMenu (name, $event) {
this.blockClosingList($event);
if (this.toggle === true && this.$scope.name == name) {
this.toggle = !this.toggle;
}
else if (this.toggle === false) {
this.toggle = !this.toggle;
}
this.$scope.name = name;
}
blockClosingList($event) {
$event.stopPropagation();
}
}
NavbarController.$inject = ['$scope', '$timeout']; // inject here and put $scope parameter in your constructor
export default NavbarController;
navbar.html - just use your html code it should work fine.
If you need to create some inner functions and keep access to this (controller) you can use arrow functions instead of function (param) {...} just use (param)=>{...} and inside brackets you will have scope of your controller.
One more thing - isolate your components as much as you can and try to communicate to parent components via $emit/$broadcasts instead of requiring parent component like in your example.
Keep in mind what I wrote above is in no way tested and most likely has bugs.
De facto best read about component based architecture in AngularJS can be found here, Todd Motto's styleguide:
https://github.com/toddmotto/angularjs-styleguide

Angularjs passing id into modal function()

I am using angularjs and spring mvc for my application. At first I am displaying all the placements with one button Placed Candidates. I am doing ng-repeat for displaying all the placements.
Here is my html.
<div class="row" data-ng-repeat="placement in placements">
<div class="col-xs-12 col-sm-12 col-md-12">
<h5>{{placement.companyName}}</h5>
</div>
<div class="col-xs-12 col-sm-6 col-md-3">
<h6>{{placement.placementDate | date:'dd MMM yyyy'}}</h6>
Company Target (appox):10 Achieved:
</div>
<a href="javascript:void(0);" data-ng-
click="placedcandidatespopup(placement.placementId);">//here i can
get particular placementId but how to pass this id to
savePlacementStudents() method in controller.js???//
PlacedCandidates
</a>
</div>
I am calling one modal popup function. Here is controller.js
$scope.placedcandidatespopup = function()
{
AdminUsersService.getAllUsers().then(function(response)
{
$scope.allusers=response.data;
console.log($scope.allusers);
})
$(".placedcandidates").modal("show");
}
I am calling modal by name "placedcandidates".
Here is the modal
<div class="modal right fade placedcandidates" id="myModal1"
tabindex="-1" role="dialog" aria-labelledby="myModalLabel2">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-body">
<div class="row">
<div class="col-xs-12 col-sm-6 col-md-6" data-ng-
repeat="student in allusers">
<input id="{{student.studentId}}" type="checkbox" value="
{{student.studentId}}" data-ng-
checked="selection.indexOf(student.studentId) >-1"
data-ng-click="toggleSelection(student.studentId)"/>
<label for="{{student.studentId}}"></label>
{{student.firstName}}
</div>
</div>
</div>
<div class="modal-footer" style="position: fixed;">
<input type="button" value="Submit" class="btn" data-ng-
click="savePlacementStudents()">
</div>
</div>
</div>
</div>
After clicking on button popup modal will display with all Students with checkboxes placed beside them.Now I am able to save studentId into database.But I am not able to pass placementId for saving.
Here is my savePlacementStudents method in controller.js.
$scope.selectedStudents = {};
$scope.savePlacementStudents = function(selectedStudents)
{
selectedStudents.selectedList = $scope.selection;
AdminPlacementService.savePlacementStudents(selectedStudents).then
(function(response)
{
if(response.data=="success"){
$window.scrollTo(0,0);
$scope.selectedStudents = {};
$scope.getplacementdetails($scope.currentPageIndex);
$scope.successmessage="Student Selection Saved!;
$timeout(function() {
$scope.successmessage="";
$scope.closeplacedcandidatespopup();
}, 1500);
}
});
}
Can anyone tell how can I pass respective placementId to this saveStudents method() so that I can set that placementId for those students selected.
Here is the solution.
The placementId passed to function placedcandidatespopup can be saved as follows in function placedcandidatespopup
$scope.selectedPlacementId = placementId;
Now the same $scope will have access in Popup also as it is using same controller.js. And now you can use this $scope.selectedPlacementId anywhere in controller.js
So you don't need to pass placementId...!!
Hope that would help you..!!
$scope.placedcandidatespopup = function(id)
{
AdminUsersService.getAllUsers().then(function(response)
{
$scope.allusers=response.data;
console.log($scope.allusers);
})
$scope.inserted = {
placementId:id,
};
var modalInstance = $uibModal.open({
templateUrl: 'views/test/myModal1.html',
controller: 'TestCntrl',
size: "Modelwidth",
resolve: {
items: function () {
return $scope.inserted;
}
}
});
}
In model you have to access using items.placementId and when you savePlacementStudents() method send placementId as well with student info.

Angular Scroll on Click

I am having an issue getting Angular Scroll to work.I am trying to scroll from the landing div to another section on the page with a button click. My code formatted really strangely, so let me know if further clarification is needed.
HTML
<div class="cover">
<div class="big-logo">
<i class="fa fa-trello"></i>
<span> My Kanban</span>
<br>
<button class="arrow" ng-click="bc.toLists()" du-smooth-scroll>
<i class="fa fa-angle-double-down fa-sm animated flash infinite" aria-hidden="true"></i>
</button>
</div>
</div>
<div class="story-board content">
<button class="add-list" ng-click="bc.addingList = !bc.addingList">
Add List
</button>
<div ng-if="bc.addingList">
<form ng-submit="bc.addList(bc.newList)">
<input style="margin-left: 5px" ng-model="bc.newList.name"/>
<button type="submit">+</button>
</form>
</div>
<div class="list" ng-repeat="list in bc.lists">
<button style="font-size: 10px;background: none;border:none; color: black" ng-click="bc.removeList(list)">x</button>
<list-component list-obj="list"></list-component>
</div>
</div>
init.js
angular.module('kanban', ['duScroll'])
app.js
angular.module('kanban')
.component('boardComponent', {
templateUrl: 'app/components/board/board.html',
controller: BoardController,
controllerAs: 'bc'
})
BoardController.$inject = ['EsService']
function BoardController(EsService) {
var bc = this;
bc.lists = EsService.getLists();
bc.addingList = false;
bc.removeList = function(list){
EsService.removeList(list.id);
}
bc.addList = function(list){
EsService.createList(list);
bc.newList = {};
}
bc.toLists = function() {
bc.cover = angular.element(document.getElementsByClassName('cover'));
bc.content = angular.element(document.getElementsByClassName('content'));
bc.cover.scrollTo(bc.content, 0, 1000);
}
}
For a JQuery free answer, you can use $anchorScroll
Create your anchor link:
<button ng-click="$ctrl.scrollTo('anid')">Scroll</button>
Create the anchor to scroll to:
<div id="anid">Land here</div>
Then your controller:
controller: function($anchorScroll) {
this.scrollTo = function(id) {
$anchorScroll(id);
}
}
I would recommend letting your controller handle the scrolling as opposed to the directives. You will have much tighter control that way and can therefore debug any issues.
Here's an example using the scrollToElement method. Once you have this logic in place you can switch it out to any method you need.
Here's a working demo
angular
.module('app', ['duScroll'])
.component('cmpExample', {
templateUrl: 'path/to/template.html',
controller: function($document) {
var vm = this;
vm.scrollTo = function(id) {
$document
.scrollToElement(
angular.element(document.getElementById(id)), 0, 1000
);
}
}
});
html
<button ng-click="$ctrl.scrollTo('target')">
<div id="target">Content further down the page</div>

Resources