Not able to obtain value in view (directive) - javascript

I have an array in the profile-form.html directive's controller.
But I am neither able to obtain the value of that array (all_languages) nor iterate over it using ng-options in the directive. It's simply printing as string. I am new to Angular and maybe doing everything terribly wrong.
Directive
app.directive("profileForm", function() {
return {
restrict: "E",
templateUrl: "/static/translatorNgApp/profile-form.html",
controller: ['$scope','$http',function($scope, $http) {
this.getCookie = function(name) {
var cookieValue = null;
if (document.cookie && document.cookie != '') {
var cookies = document.cookie.split(';');
for (var i = 0; i < cookies.length; i++) {
var cookie = jQuery.trim(cookies[i]);
// Does this cookie string begin with the name we want?
if (cookie.substring(0, name.length + 1) == (name + '=')) {
cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
break;
}
}
}
console.log(cookieValue);
return cookieValue;
};
$scope.csrftoken = this.getCookie('csrftoken');
$scope.myForm={};
$scope.all_languages = ['English', 'Hindi'];
$scope.language_pairs = [];
$scope.getAllLanguages = function () {
$http.get('/getAllLanguages'
).success(function(response) {
// success
$scope.all_languages.concat(response);
}).error(function(response) {
// failed
});
};
$scope.submitForm = function() {
var postData = {
method: 'POST',
url: '/accounts/tprofile/',
// headers : {'Content-Type':'application/x-www-form-urlencoded; charset=UTF-8'},
headers: {'X-CSRF-Token' : $scope.csrftoken },
data: $scope.myForm
};
$http(postData)
.then(function(response) {
// success
},
function(response) { // optional
// failed
});
console.log("Form submitted");
// $scope.message = "Sent Successfully 2";
// console.log(postData);
console.log(postData);
console.log($scope.myForm);
};
$document.ready(function(){
console.log("document ready");
$scope.getAllLanguages(); //This can be commented out for the question's sake.
});
}],
controllerAs: "profileFormCtrl"
};
});
Directive Template (profile-form.html)
<div class="form-group" >
<label for="id_source_language">Source language: </label>
<ul>
<li>
<pre>all_languages = {{all_languages | json}}</pre>
<select data-ng-model="source" ng-options="language for language in all_languages" class="form-control" id="id_source_language" name="source_language" placeholder="Source Language" required>
</select>
<button ng-click="language_pairs.pop($index)" aria-label="Remove">Remove</button>
<button ng-click="language_pairs.push({})">Add more pair</button>
</li>
</ul>
</div>

Using document.ready event inside a angular directive doesn't make sense to call specific method of scope. Because document.ready event has already happened after that event only angular started process page.
Ideally to make your code working state you need to remove $document.ready(function(){ .... }); code which isn't required there. And as document.ready is already accomplished, so the one which you had registered from directive wouldn't get call.

Related

AngularJS insert data twice to database

I am trying to insert data to database through angularJS but the data inserted twice.. I have tried to use ngRoute but still I face the same problem.
app.js
var app = angular.module("addDepApp", []);
app.controller('insertDepCtl', function($scope, $http) {
var isSend = false;
$scope.$on('newuser', function(event, data){
load(true);
});
var load = function(isEvent){
if($scope.$parent.newuser != null){
isSend = true;
}
};
load();
$scope.insertDepartment = function () {
console.log("called insertDepartment");
if (isSend == true){
$scope.newuserSend = {'org_id': $scope.$parent.newuser.org_id, 'dep_name': $scope.department};
$http.post("http://192.168.1.12:8888/XXXX/XXX/insertDep.php/",$scope.newuserSend)
}
}
});
add.html
<body ng-app="addDepApp">
<div class="12u$" ng-controller="insertDepCtl">
<input type="button" value="تسجيل" class="special" id="signup" ng-click="insertDepartment()"/>
</div>
</body>
Remove ng-controller="insertDepCtl" from your html code, your router injects this for you. Right now, you're calling everything twice
I have changed the code to this and now it works fine!!
$scope.insertDepartment = function () {
if (isSend == true) {
var request = $http({
method: "post",
url: "http://192.168.1.106:8888/XXXX/XXX/insertDep.php/",
data: {'org_id': $scope.$parent.newuser.org_id, 'dep_name': $scope.department},
headers: {'Content-Type': 'application/x-www-form-urlencoded'}
});
}
}

angularjs call function from html return value

I'm new to AngularJS.
I want to call a function from html.
<td>
{{getComponentSubtype(component.ID)}}
</td>
However, the function calls a webapi and waits for a callback. How do i get the data to show up in the html?
function getComponentSubtype(componentId) {
apiService.get('/api/components/' + componentId + '/componentSubtype', config,
getComponentSubtypeCompleted,
getComponentSubtypeFailed);
}
function getComponentSubtypeCompleted(result) {
$scope.ComponentSubtype = result.data;
//////I WANT TO RETURN $scope.ComponentSubtype.Name//////
}
call the function from HTML and once callback is received store its value in a JSON object which can be printed in HTML. Meanwhile show a loading message in UI
HTML:
{{ getComponentSubtype(component.ID) }}
<td ng-if="componentsSubType[component.ID] != null">
{{ componentsSubType[component.ID] }}
</td>
<td ng-if="componentsSubType[component.ID] == null">Loading Component ...</td>
Controller:
function getComponentSubtype(componentId) {
apiService.get('/api/components/' + componentId + '/componentSubtype', config,
function(result) {
if ($scope.componentsSubType == null) {
$scope.componentsSubType = {};
}
$scope.componentsSubType[componentId] = result;
},
function() {
if ($scope.componentsSubType == null) {
$scope.componentsSubType = {};
}
$scope.componentsSubType[componentId] = "Load Failed";
});
}
Note: I have assumed that in HTML you are getting component from a loop (ng-repeat)
in your HTML ...
<td>{{myvariable}}</td>
in your controller ...
angular.module('yourApp').controller('ControllerName', function($scope, apiService) {
$scope.myvariable = 'please wait';
function initComponent(id) {
apiService.get('/api/components/' + id + '/componentSubtype').then(function(response) {
$scope.myvariable = response;
}).catch(function(failedResponse) {
// handle failure here
console.log('oops', failedResponse);
});
}
initComponent(500);
});
This is quite likely not ideal, but I would need to know more about your code for a better solution.
You could use an object to store the types and access that in your template:
<td>{{ componentSubtypes[component.id] }}</td>
Call getComponentSubtype for each component id:
$scope.componentSubtypes = {};
components.forEach(function(component) {
getComponentSubtype(component.id);
});
function getComponentSubtype(componentId) {
apiService.get('/api/components/' + componentId + '/componentSubtype', config,
getComponentSubtypeCompleted(componentId),
getComponentSubtypeFailed);
}
// Using a closure here for the id
function getComponentSubtypeCompleted(id) {
return function(result) {
$scope.componentSubTypes[id] = result;
// ...
}
}

Prevent ng-repeat until request data is fully loaded

Im trying to prevent ng-repeat runs before the request data is fully loaded into an array, I've done it using a timeout but it only works when the request takes less than I say
Here is my HTML:
<div class="blocks-container" ng-init="loadProjects()" ng-controller="buildMonitorController">
<div class="row">
<!-- <div> -->
<div class="col-xs-12 col-sm-6 col-md-3 col-lg-2 block animate"
ng-if="!errorDialogActive && finishedRequest"
ng-repeat="build in builds.builds.build track by build._id | orderBy:'lastBuildDetails.startDate' : true"
ng-class="{'running': project.running ,'block-green': build._status ==='SUCCESS','block-red': build._status==='FAILURE'}"
id="{{build._id}}">
<div class="title-container"><p>{{build._buildTypeId}}</p></div>
<div class="update-container col-xs-12">
<time>{{ build.lastBuildDetails.startDate | date : 'dd.MM.yyyy H:mm:s'}}</time>
</div>
</div>
<!--</div>-->
</div>
<!-- Start error state dialog -->
<div ng-include src="'views/main/error-dialog.html'"></div>
And Here is my AngularJS:
$scope.refreshBuilds = function () {
$scope.errorList.length = 0
//#TODO remove this part right after the API is working
//Init
var suffix = '';
var randomnumber = Math.floor(Math.random() * 3);
//simulate mock by random number
switch (randomnumber) {
case 1:
suffix = '-success';
break;
case 2:
suffix = '-less';
break;
default:
break;
}
var url = 'mock/builds'+suffix+'.xml';
console.log('url: ' + url)
$http({
method: 'GET',
url: url,
headers: {
Authorization: 'Basic AAA'
}
}).success(function (data, status) {
//Recive builds from xml and reset scope
var buildsToFilter = new X2JS().xml_str2json(data);
$scope.errorDialogActive = false;
//filter builds which have a no build API detail status
if (buildsToFilter.builds.build !== undefined) {
angular.forEach(buildsToFilter.builds.build, function (build, index) {
$http({
method: 'GET',
url: 'mock/build-'+build._id+'.xml',
headers: {
Authorization: 'Basic AAA'
}
}).success(function (buildDetailData) {
$scope.errorDialogActive = false;
//push detail data into build array
buildsToFilter.builds.build[index].lastBuildDetails = new X2JS().xml_str2json(buildDetailData).build;
console.log(buildsToFilter.builds.build[index]);
}).error(function (data, status) {
$scope.errorDialogActive = true;
//remove build from index if no build detail was found
buildsToFilter.builds.build.splice(index, 1);
$scope.setError(status, '', '');
}).then(function () {
//after filtering builds to display, setup builds $scope for FrontEnd
$scope.builds = buildsToFilter;
});
});
} else {
}
}).error(function (data, status) {
//active dialog if error happens & set error
$scope.errorDialogActive = true;
$scope.setError(status, 'builds', '');
}).then(function () {
$timeout(function () {
$scope.finishedRequest = true;
}, 5000);
//refresh right after proceed and a little delay
$timeout(function () {
console.log('Starting refresh');
$scope.refreshBuilds();
}, 21000);
})
};
You can put condition
ng-show=builds.builds.build.length > 0
So when the builds.builds.build have data then only it will be displayed
You already have that
ng-if="!errorDialogActive && finishedRequest"
in place, but you never set $scope.finishedRequest = false. What if you simply modify your refreshBuilds function like this:
$scope.refreshBuilds = function () {
$scope.finishedRequest = false;
$scope.errorList.length = 0;
// etc
Does it work then in the way you wanted?

HTML table not updating, after pushing new item to knockout observableArray

I am having trouble updating my HTML UI.
When the document load and calls "getAllProducts()", the HTML UI displays all my items and with the right css class for 'styleStatusCss', and the right 'displayName', the problem is that when I try to update my observableArray with a newly updated product (product name or status has changed), the html UI does not update and remains the same
So here is a quick list of what is happening:
getUpdatedProducts() is called every 25 sec, and returns, any product
that has been updated
I check how many products my observable array has: appVM.itemList.length and it does have 100 (as expected!), I also check that the json product that has been sent back has some modified data, and indeed it has changed!
I then create the javascrip obj MyProduct using that product json object
Now I add my newly created javascript obj MyProduct to the observablearray: appVM.itemList.push(newUpdatedProduct);
And finally I check how many items my observablearray has, after doing the push, (and since I cannot see any changes on the HTML UI), and appVM.itemList.length now says 101 !!! How can that be? the HTML UI still displays the data as it was after the initial load
Please see below most of the code
HTML
<table >
<tbody data-bind="foreach: itemList">
<tr>
<td>
<div data-bind="css: styleStatusCss"></div>
</td>
<td>
<div data-bind="text: displayName"></div>
</td>
</tr>
</tbody></table>
And here is the javascript:
<script type="text/javascript">
var appVM;
var initializeItems = false;
$.ajaxSetup({
// Disable caching of AJAX responses
cache: false
});
$(document).ready(function () {
getAllProducts();
});
setInterval(function () {
if (initializeItems) {
getUpdatedProducts();
}
}, 25000);
function getAllProducts() {
var url = '#Url.Action("_AllProducts", "Home")';
$.ajax({
url: url,
type: 'GET',
dataType: 'JSON',
})
.success(function (result) {
initializeItems = true;
appVM = new AppViewModel();
var mappedProducts = ko.utils.arrayMap(result.ItemList, function (item) {
var con = new MyProduct(item);
return con;
});
appVM.itemList = mappedProducts;
ko.applyBindings(appVM);
})
.error(function (xhr, status, error) {
alert("FATAL ERROR");
})
}
function getUpdatedProducts() {
var url = '#Url.Action("_UpdateProducts", "Home")';
$.ajax({
url: url,
type: 'GET',
dataType: 'JSON',
})
.success(function (result) {
if (result.HasNewData) {
alert("we have some data");
alert("START COUNT: " + appVM.itemList.length); //this shows all my 100 products -> START COUNT: 100
alert("Number of new items: " + result.ItemList.length); // i only get one product back for easy debugging
for (index = 0; index < result.ItemList.length; ++index) {
var updatedProdJson = result.ItemList[index]; //get the json for the product
alert("New prod json: " + objToString(updatedProdJson)); //just for debugging print out in a readable format
var newUpdatedProduct = new MyProduct(updatedProdJson);//create our MyProduct object (which has all properties as observable)
appVM.itemList.push(newUpdatedProduct); //add our new MyProduct to the list
alert("FINAL COUNT: " + appVM.itemList.length); // --> FINAL COUNT: 101
}
}
})
.error(function (xhr, status, error) {
alert("Error: " + status);
})
}
function AppViewModel() {
var self = this; //so it references the viewModel object
self.itemList = ko.observableArray([]);
self.doAlert = function () {
alert("HERE");
}
}
function MyProduct(data) {
//alert("DATA: " + objToString(data));
this.Id = ko.observable( data.Id);
this.Name = ko.observable(data.Name);
this.status = ko.observable(data.Status);
this.displayName = ko.computed(function () {
var fullnmae = this.Id() + " " + this.Name();
return fullnmae;
}, this);
this.styleStatusCss = ko.computed(function () {
var pStatus = 'divstatusnone';
if (this.status() === 'H')
pStatus = 'divlowstatus';
if (this.status() === 'D')
pStatus = 'divhighstatus';
return pStatus;
},this);
}
function objToString (obj) {
var str = '';
for (var p in obj) {
if (obj.hasOwnProperty(p)) {
str += p + '::' + obj[p] + '\n';
}
}
return str;
}
Hope somebody can tell me where i went wrong.
Many thanks,
in getAllProducts, you're assigning the results to itemList, losing your observable array:
appVM.itemList = mappedProducts;
you need to do this instead:
appVM.itemList(mappedProducts);

How to append/display/render data to page on click

I want to get the data from the API and display it on my index.html page. What's the best way in doing this? looking for multiple ways, that be jquery or data binding with angular. I can't seem to figure out a function to display the data I get. I'm fetching two different datas from two different players and I want to display them side by side. JSON data is returned by the API
/**Part of Index.html**/
<body ng-app="lolvs" ng-controller="MainController">
<div class="throwdown">
<h1> LoL THROWDOWN </h1>
<div class="summonerNames">
<input id="summonerOne" ng-model="summonerOne" placeholder="summoner name">
<button class="start" ng-click="start()">vs</button>
<input id="summonerTwo" ng-model="summonerTwo" placeholder="summoner name">
</div>
/**app.js**/
(function(){
'use-strict'
var mainCtrl = function mainCtrl($scope, $rootScope, MainFactory) {
$scope.start = MainFactory.start;
$rootScope.$on('gotStats', function (e, m) {
console.log('arguments >>', arguments);
$scope.player1 = {
totalChampionKills : 0,
totalDeathsPerSession : 0,
totalAssists : 0,
totalSessionsWon : 0,
totalSessionsLost :0,
totalMinionKills: 0,
totalTurretsKilled: 0,
};
$scope.apply();
});
};
var mainFactory = function ($http, $rootScope) {
var api = 'api_key=***************************';
var add = function(data, status, headers) {
var stats = {
totalChampionKills : 0,
totalDeathsPerSession : 0,
totalAssists : 0,
totalSessionsWon : 0,
totalSessionsLost :0,
totalMinionKills: 0,
totalTurretsKilled: 0,
};
var champions = data.champions;
for(var i = 0; i < champions.length; i++) {
var champ = champions[i].stats;
for(stat in stats) {
if(champ[stat]) {
stats[stat] += champ[stat]
}
}
}
};
var start = function(name) {
var options = {
url: 'https://na.api.pvp.net/api/lol/na/v1.4/summoner/by-name/' + name + '?' + api,
type: 'GET',
success: summonerOption
};
$http(options);
};
var summonerOption = function(data, status, headers) {
var name = Object.keys(data)[0];
var newOption = {
url: 'https://na.api.pvp.net/api/lol/na/v1.3/stats/by-summoner/' + data[name].id + '/ranked?season=SEASON4&' + api,
type: 'GET',
success: add
};
$http(newOption);
};
return {
start: start
}
};
angular.module('lolvs', [])
.controller('MainController', ['$scope', '$rootScope', 'MainFactory', mainCtrl])
.factory('MainFactory', ['$http', '$rootScope', mainFactory])
})();
What kind of data is being returned? If it is a json array, you might want to iterate through it before printing the whole thing to your webpage.
In theory however, you should handle the data after a successful ajax call, which seems to be executed after pressing the <button> in your index.html..
This could look like so:
var newOption = {
url: 'https://na.api.pvp.net/api/lol/na/v1.3/stats/by-summoner/' + data[name].id + '/ranked?season=SEASON4&' + api,
type: 'GET',
success: function(data) {
$('.containerForData').html('<div class="data-wrap">' + data + '</div>');
}
};
Unfortunately your question is not very clear, but I hope this helps.

Categories

Resources