Angular nested state has to use $scope.parent from same controller, why? - javascript

I have a table, which loops over a scope called $scope.sites.
I'm submitting a form which saves a new site to a DB, and then adds to the site scope.
However, when I update $scope.sites, it doesn't update the table. The table is under the same SiteCtrl controller.
The scope is definitely being appended to, as if I output {{ sites.length }} after the form has posted, its value increases (and the data appears in the DB).
If I add {{ sites.length }} to the same part that the form is included (in the ui-view) it updates, outside of that and it doesn't.
Here's some of the code:
The Javascript
Note, I'm using ui-router for nested states.
myApp.config(function($stateProvider, $urlRouterProvider){
// The default route
$urlRouterProvider.otherwise('/home');
$stateProvider
.state('home', {
url: '/home',
templateUrl: 'app/partials/welcome.html',
controller: 'WelcomeCtrl'
})
.state('entity', {
url: '/entity/:id',
params: { id: "" },
templateUrl: 'app/partials/entity/index.html',
controller: 'EntityCtrl'
})
.state('entity.site', {
url: '/site',
templateUrl: 'app/partials/site/index.html',
controller: 'SiteCtrl'
})
.state('entity.site.create', {
url: '/create',
templateUrl: 'app/partials/site/create.html',
controller: 'SiteCtrl'
})
....
myApp.controller('SiteCtrl', ['$scope', '$http', '$stateParams', function($scope, $http, $stateParams) {
$scope.entity_id = $stateParams.id;
$scope.site_uuid = $stateParams.siteuuid;
$scope.sites = {};
$scope.site = {};
$scope.errors = {};
$scope.result = {};
$scope.formData = {};
$http({ method: 'GET', url: 'siteurl' }).
success(function (data, status, headers, config) {
$scope.sites= data.data;
}).
error(function (data, status, headers, config) {
console.log(data.result);
console.log(data.code);
});
$scope.submitForm = function() {
$http.post('submiturl', $scope.formData).success(function(data) {
//Clear the form
$scope.formData = {};
$scope.site = data.data;
$scope.sites.push($scope.site);
}).error(function(data){
$scope.errors = data;
});
}
}]);
The HTML
<div ng-controller="SiteCtrl">
<h1>Sites <a ui-sref="entity.site.create" class="btn"><i class="fa fa-plus"></i> Add New Site</a></h1>
<ui-view></ui-view> <!---- The form is included here by a ui-router state --->
<pre>{{ sites.length }}</pre> <!-- this doesnt update, nor does the table --->
<div class="form-group">
<label for="filter">Filter</label>
<input ng-model="filter" class="form-control">
</div>
<table class="striped">
<thead>
<tr>
<td>Name</td>
</tr>
</thead>
<tbody>
<tr ng-repeat="site in sites | filter:filter">
<td><a ui-sref="entity.site.show({siteuuid:site.uuid})" ui-sref-active="child-active">{{ site.name }}</a></td>
</tr>
</tbody>
</table>
The Form
<h1>Create a New Site at {{ entity.name }} <a ui-sref="entity.site" class="btn">Close</a></h1></h1>
<pre>{{ result }}</pre>
<pre>{{ errors }}</pre>
<pre>{{ site }}</pre>
<pre>{{ sites.length }}</pre> <!---- This updates --->
<form name="createNewSiteForm" method="post" ng-submit="submitForm()">
<div class="form-group">
<label for="name">Site Name</label>
<input type="text" name="name" class="form-control" ng-model="formData.name" autocomplete="off" required />
{{ errors.name }}
</div>
<div class="form-group">
<input type="submit" name="create" value="Save {{ formData.name }}" />
</div>
</form>
The form is included as a nested view in the
If there's anything else you'd like to see let me know and I can post it up.
Update
So the solution was to use:
$scope.parent.sites.push($scope.site);
My question is, do I have to use the parent, when the scope should be inherited due to being in the same Controller?
I'm new to Angular shedding some light on this would be very useful for my learning.

Related

Editing data in AngularJS

I just began to study angular, tried to make some kind of SPA, but faced with problem of editing data in it. The obect is visible in console, but it hasn't appear on page, what I did wrong?
Here my controller:
var app = angular.module("testModule", ['ngRoute']);
app.config(function ($routeProvider){
$routeProvider.when('/', {
templateUrl: 'pages/main.html',
controller: 'addCtrl'
})
.when('/save', {
templateUrl: 'pages/save.html',
controller: 'editCtrl'
})
.when('/edit', {
templateUrl: 'pages/edit.html',
controller: 'addCtrl'
})
})
app.service('dataService', function($http) {
var data = {};
data.list = [];
var getData = function() {
$http.get("model/data.json").then(function (response) {
data.list = response.data;
});
}
return {
getDataFromJson: getData,
getData: data,
}
});
app.controller("mainCtrl", function($scope, dataService) {
dataService.getDataFromJson();
});
app.controller("editCtrl", function($scope, dataService) {
$scope.data = dataService.getData;
$scope.editData = function(adverse){
$scope.adverse= adverse;
console.log($scope.adverse)
}
});
and the part of page:
<div class="panel">
<form name="addForm" >
<div class="well" >
<div class="form-group">
<label for="name">Name:</label>
<input type='text' id="name" class="form-control" ng-model="adverse.name" placeholder={{adverse.name}} />
<label for="shop">Shop:</label>
<input type='text' id="shop" class="form-control" ng-model="adverse.shop" placeholder="{{adverse.shop}}" />
<label for="begin">Begin:</label>
<input id="begin" class="form-control" ng-model="adverse.begin" placeholder="{{adverse.begin}}" >
<label for="end">End:</label>
<input id="end" class="form-control" ng-model="adverse.end" placeholder="{{adverse.end}}" />
<button type="submit" class="btn btn-primary btn-block add_btn" ng-click="editData(adverse)">
Edit
</button>
</div>
</div>
</form>
</div>
Also here is a screenshot: the props of object suppose to be in the inputs but it hasn't.
enter image description here
If possible can you give me an example how I can do it by another way?
Recreated your scenario in this plunker. But it works. Please have a look at this plunker where you alo can see the StateProvider which is used instead of NgRoute
One thing I see which is incorrect is that you are sending the adverse object in the function and then setting the param to the scope adverse.
The thing is that the $scope.adverse already holds the values so you don't need to pass the value and setting it to the scope again. Remeber the scope is your glue between the view and ctrl
$scope.editData = function(){
console.log($scope.adverse)
}

Page not updating in AngularJS

I am creating a web app, where I have one page which is home.html and about.html. In the home.html I have list of users, and when they click on one of the users, it goes to about.html, but does not show the users info. Can anyone check my code, to see what I have done wrong. Thanks in advance.
Here is my code. (home.html)
<form name="myForm">
<label>Search
<input type="text" size="35" ng-model="userSearch">
</label>
</form>
<br/>
<label>Filters</label>
<button type="button" class="btn btn-link">+ Add Filter</button>
<hr>
<legend>Users</legend>
<div class="people" ng-repeat="person in userInfo.lawyers | filter:userSearch" >
<a href="#/lawyer/{{ person.id }}">
<img ng-src="{{person.imgUrl}}"/>
<span class="name">{{person.firstName}} </span>
<span class="name">{{person.lastName}} </span>
<p class="title">{{person.title}} </p>
<span class="date">{{person.date}} </span>
</a>
</div>
About.html
<div class="people-view">
<h2 class="name">{{person.first}}</h2>
<h2 class="name">{{person.last}}</h2>
<span class="title">{{person.title}}</span>
<span class="date">{{person.date}} </span>
</div>
<div class="list-view">
<form>
<fieldset ng-disabled="inactive">
<legend>Basic Info</legend>
<b>First Name:</b>
<input type="text" ng-model="person.first">
<br>
<b>Last Name:</b>
<input type="text" ng-model="person.last">
<br>
<b>Email:</b>
<input type="email" ng-model="person.email">
<br>
<b>Phone:</b>
<input type="num" ng-model="person.phone">
<br>
<b>Website:</b>
<input type="text" ng-model="person.website">
<br>
<b>Education:</b>
<input type="text" ng-model="person.education">
<br>
<b>Education Year:</b>
<input type="text" ng-model="person.year">
<br>
</form>
</div>
</div>
App.js
var app = angular.module("Portal", ['ngRoute', 'ui.bootstrap' ]);
app.controller('MyCtrl', function($scope) {
//form setting to true
$scope.inactive = true;
$scope.confirmedAction = function() {
isConfirmed.splice($scope.person.id, 1);
location.href = '#/lawyer';
}
});
app.config(function ($routeProvider) {
$routeProvider
.when("/lawyer", {
controller: "HomeController",
templateUrl: "partials/home.html"
})
.when("/lawyer/:id", {
controller: "LawyerController",
templateUrl: "partials/about.html"
})
.otherwise({
redirectTo: '/lawyer'
});
});
Controller
app.controller('LawyerController', ['$scope', 'people', '$routeParams',
function ($scope, people, $routeParams) {
people.getUserInfo().then(function (response) {
$scope.person = people.getUserInfo();
console.log($scope.person.lawyers);
}, function (error) {
console.log(error)
});
}]);
HomeController
var isConfirmed = false;
app.controller('HomeController', function($scope, people, $http) {
if (!isConfirmed) {
people.getUserInfo().then(function (response) {
$scope.userInfo = response.data;
isConfirmed = $scope.userInfo;
console.log($scope.userInfo.lawyers);
}, function (error) {
console.log(error)
});
}
});
Services
app.factory('people', ['$http', function($http) {
var userInfo = {
getUserInfo: function () {
return $http.get('https://******************');
}
};
return userInfo;
}]);
As others mentioned, your whole code is in wrong way! but I will try to help as much as I can.
You don't have any method in LawyerController to get the data, so let's begin from that :
change your $routeProvider in app.js like this to have a method :
$routeProvider
.when("/lawyer", {
controller: "HomeController",
templateUrl: "partials/home.html"
})
.when("/lawyer/:id", {
controller: "LawyerController",
templateUrl: "partials/about.html",
method: 'lawyerInit'
})
.otherwise({
redirectTo: '/lawyer'
});
Then change your LawyerController to something like this :
app.controller('LawyerController', ['$scope', 'people', '$routeParams',
function ($scope, people, $routeParams) {
$scope.lawyerInit = function(){
people.getUserInfo().then(function (response) {
$scope.getAll= people.getUserInfo();
for (var i=0; i<=$scope.getAll.length -1; i++){
if($scope.getAll[i].lawyers.id==$routeParams.id){
$scope.person= $scope.getAll[i];
}
}
console.log($scope.person.lawyers);
}, function (error) {
console.log(error)
});
}
}]);
Hope this work, I was not sure how is your json response, if you get error in this line if($scope.getAll[i].lawyers.id==$routeParams.id) you need make sure the id where is exactlly in your json object.

Data passing through controller in REST api

I am new in Ionic and angularjs. I am trying to fetch login (ng-model) data (email&password) from signin.html page, and calling API with POST method.But it doesn't call api. I spent couple of days for this. Please help me!
html
<ion-view view-title="login">
<ion-component>
</br>
<div class="list list-inset">
<label class="item item-input">
<input type="text" placeholder="First Name" ng-model="login.firstname">
</label>
<label class="item item-input">
<input type="password" placeholder="Password" ng-model="login.password">
</label>
<label class="item item-input">
<input type="text" placeholder="E-mail" ng-model="login.email">
</label>
<button class="button button-block button-balanced" data-ng-click="submit(login)">
Login
</button>
<button class="button icon-left button-block ion-social-facebook button-positive">Login Facebook</button>
<button class="button icon-left button-block ion-social-googleplus button-assertive">Login Google+</button>
<a ng-href="#/signup"><button class="button button-clear button-positive">SignUp
</button></a>
</div>
</ion-component>
</ion-view>
app.js
var app=angular.module('starter', ['ionic','ngCordova'])
app.controller('loginCtrl', function($scope,$http){
$scope.data=[];
// $scope.logindata = {};
// console.log (login);
$scope.login={};
//****login submit****
$scope.submit=function(login){
console.log(login);
$scope.logincontet=console.log('logindata:'+login);
//***api call***
var local1='json={"method_name":"login","body":{"login_with":"2","facebook_id":"","email":';
var local2=',"name":"",';
var local3='"password":';
var local4='}}';
var req =
{
method: 'POST',
url: "http://192.168.1.23/projects/veterinary/webservice/main.php",
//data: 'json={"method_name":"login","body":{"login_with":"2","facebook_id":"","email":"$scope.login.email","name":"","password":"$scope.login.password"}}',
data:local1 + $scope.login.email + local2 + local3 + $scope.login.password +local4,
headers: {"Content-Type": "application/x-www-form-urlencoded"}
};
$http(req).success(function(data, status, headers, config)
{
console.log('Success',data);
$scope.data=data.data;
//success
})
.error(function(data, status, headers, config)
{
console.log('Error');
});//error
//*********
window.location.href = "#/success.html";
}
//*****
//****login api call****
});
app.config(function($stateProvider, $urlRouterProvider){
$stateProvider
.state('login', {
url: "/login",
templateUrl: "templates/login.html",
controller: 'loginCtrl'
})
.state('signup', {
url: "/signup",
templateUrl: "templates/signup.html",
controller: 'signupCtrl'
})
// if none of the above states are matched, use this as the fallback
$urlRouterProvider.otherwise('/login');
});
*********************
Binding view and controller!
Finally I created post api string with this...
data: 'json={"method_name":"login","body":{"login_with":"2","facebook_id":"","email":"'+$scope.login.email+'" ,"name":"","password":"'+$scope.login.password+'"}}',

editing form in angular way

I am new to angular. I have the post list view and post edit view. my list.html. I want to edit the post on clicking the edit button but I am not having a clue on how to get the edit data. My current code looks like
list.html
<table class="table table-striped table-bordered table-hover table-full-width" id="sample_1">
<thead>
<th>Title</th>
<th>Description</th>
<th>Author</th>
<th>Action</th>
</thead>
<tbody>
<tr ng-repeat="post in blog | orderBy:'created_at':true">
<td>{{post.title}}</td>
<td>{{post.description}}</td>
<td>{{post.author}}</td>
<td>
Edit
Delete
</td>
</tr>
</tbody>
</table>
So, on clicking the button, I am navigating to my edit.html which looks like
<form role="form" class="form-horizontal" ng-submit="editPost()">
<div class="form-group">
<label class="col-sm-2 control-label" for="form-field-1">
Title
</label>
<div class="col-sm-9">
<input type="text" placeholder="Post title" id="form-field-1" class="form-control" ng-model="blog.title" value="{{blog.title}}">
</div>
</div>
<div class="form-group">
<label class="col-sm-2 control-label" for="form-field-2">
Description
</label>
<div class="col-sm-9">
<textarea placeholder="description" rows="5" id="form-field-2" class="form-control" ng-model="blog.description"></textarea>
</div>
</div>
<div class="form-group">
<label class="col-sm-2 control-label" for="form-field-1">
Author
</label>
<div class="col-sm-9">
<input type="text" placeholder="Author" id="form-field-1" class="form-control" ng-model="blog.author">
</div>
</div>
<div class="form-group">
<div class="col-sm-9 col-sm-offset-2">
<button type="submit" class="btn btn-primary btn-sm">Update</button>
</div>
</div>
</form>
now I have make restful api using nodejs which I have tested using postman and its working fine. My api url are like
localhost:3000/api/posts/id
What I want to achieve now is, I want to get the data from the db on clicking the edit button.
my current js declaration
var meanApp = angular.module('meanApp', ['ui.router', 'ngMessages', 'ngResource']);
meanApp.config(function($stateProvider, $urlRouterProvider) {
$urlRouterProvider.otherwise('/');
$stateProvider
.state('common', {
abstract: true,
views: {
'': {
templateUrl: 'shared/common.html'
},
'header#common': {
templateUrl: 'shared/header.html'
},
'sidebar#common': {
templateUrl: 'shared/sidebar.html'
},
'script#common': {
templateUrl: 'shared/script-init.html'
},
},
})
.state('blogEdit', {
url: '/blog/edit/{id}',
parent: 'common',
views: {
'': {
templateUrl: 'components/blog/edit.html'
},
},
controller: 'postEditController'
})
});
meanApp.controller('postEditController', function(postService, $stateParams, $scope, $http, $location) {
//code to get the data from db using the id of the post
});
Any help will be appreciated.
If your trying to achieve the data from Db using nodejs.I gave my working example nodejs code (DB connectivity),
var pool = require('../config/database');
module.exports.findCampaign = function(req, res) {
//You created properties file and access or using direct query like this
//var findCampaign = select * from campaigns where campaign_sno = ?
// Accessing properties file
var findCampaign = campaignSql.get('main.findCampaign');
pool.query(findCampaign, function(err, rows) {
if (err)
throw err;
// You follow your coding standard here i did example or reference purpose i wrote like this
console.log('Data received from Db:\n');
console.log(rows);
});
};
in your config file where you are routing with ui.router....in the edit blog state:
.state('blogEdit', {
url: '/blog/edit/:id',
parent: 'common',
views: {
'': {
templateUrl: 'components/blog/edit.html'
},
},
controller: 'postEditController'
})
this :id will be treated as url parameters. now in the controller:
meanApp.controller('postEditController', function(postService, $stateParams, $scope, $http, $location) {
postService.getPostById(parseInt($stateParams.id, 10));
});
here, if your id contains character..... you may not have to parse. Now, query your Db in the service..... since you now have the parameter.....
$http({
url: 'your/path/to/server',
method: "GET",
params: {user_id: idFromServiceArgument}
});

Exception while simulating the effect of invoking '/todos/update'

I am building a TODO application using Angular-Meteor.I am following the tutorial here:
http://angularjs.meteor.com/tutorial/step_06
I have an error while I am trying to access a single todo item:
Here is my app.js
Todos = new Mongo.Collection('todos');
if (Meteor.isClient) {
var todo = angular.module('todo', ['angular-meteor', 'ui.router']);
todo.config(['$urlRouterProvider', '$stateProvider', '$locationProvider', function($urlRouterProvider, $stateProvider, $locationProvider) {
$locationProvider.html5Mode(true);
$stateProvider
.state('todos', {
url: '/todos',
templateUrl: 'todos-list.ng.html',
controller: 'todoListController'
})
.state('todoDetails', {
url: '/todos/:todoId',
templateUrl: 'todo-details.ng.html',
controller: 'todoDetailsController'
});
$urlRouterProvider.otherwise("/todos");
}]);
todo.controller('todoListController', ['$scope', '$meteor', function($scope, $meteor) {
$scope.todos = $meteor.collection(Todos);
$scope.addTodo = function(todo) {
todo.date = new Date();
$scope.todos.save(todo);
};
$scope.remove = function(todo) {
$scope.todos.remove(todo);
};
$scope.clear = function() {
$scope.todos.remove();
};
}]);
todo.controller('todoDetailsController', ['$scope', '$stateParams','$meteor', function($scope, $stateParams, $meteor) {
$scope.todoId = $stateParams.todoId;
$scope.todo = $meteor.object(Todos, $stateParams.todoId);
}]);
}
My index.html:
<head>
<base href="/">
</head>
<body>
<div ng-app="todo">
<h1>
Home
</h1>
<div ui-view></div>
</div>
</body>
My todo-list.ng.html
<form>
<label for="name">Name</label>
<input type="text" id="name" ng-model="newTodo.name">
<label for="priority">Priority</label>
<input type="text" id="priority" ng-model="newTodo.priority">
<button class="btn btn-primary" ng-click="addTodo(newTodo)">Add Todo</button>
</form>
<ul>
<li ng-repeat="todo in todos track by $index">
{{todo.name}} {{todo.priority}} {{todo.date | date}}
<button class="btn btn-primary" ng-click="remove(todo)">Done</button>
</li>
<h4>Tasks to do: {{todos.length}}</h4>
</ul>
<button class="btn btn-primary" ng-click="clear()">Clear list</button>
And todo-details.ng.html
<h1>Your to do</h1>
<input type="text" ng-model="todo.name">
<input type="text" ng-model="todo.priority">
I have no idea, what am I doing wrong, following the official tutorial step by step, just replace parties with todo, honestly.
Any ideas ?
It turns out it was a bug caused by Meteor itself.
I have created an issue on Github and it was fixed.

Categories