I have a subscription feature which is open through checking a radio box. When open inside this section I have 2 radio buttons for subscribe the period weekly or monthly and below an item. When I pressing save the state of this period have to be saved for one item I have from the server. You can check the screenshot to see the view. Anyway, there is no save because the array result empty and that item is not in that array. My problem is I see the item below but somehow I'm not pushing it into the array with the period selected from radio buttons. I would like to receive help to understand why of that and what I should modify to make it works properly.
Please check the code I'm sharing controller and view:
searchApp.controller('UserSettingsCtrl', ['$scope', '$q', '$rootScope', 'aiStorage', 'userConfig', 'UserSettingsService', 'WebsiteSource', 'AnalyticsEmailService', 'toaster', '$translate', '$filter', 'ngTableParams',
function($scope, $q, $rootScope, store, userConfig, UserSettingsService, WebsiteSource, AnalyticsEmailService, toaster, $translate, $filter, ngTableParams) {
$scope.init = function() {
$scope.availableLanguages = {
da: 'Dansk',
en: 'English',
sv: 'Svensk'
}
window.scope = $scope
$scope.userInfo = store.get('user')
$scope.loadingAction = false
$scope.selectFlag = false
$scope.subscriptionEnginesFromServer = []
$scope.subscriptionEngines = []
$scope.analyticsEmailSettings = {}
$scope.engines = angular.copy(WebsiteSource.sites)
AnalyticsEmailService.getUserSubscription().then(
function success(response) {
$scope.loadingAction = false
$scope.subscription = response
console.log('response.data', response.data)
$scope.subscriptionEnginesFromServer = populateSubscribedEnginesFromServer(response.data)
getUnselectedEngines()
$scope.analyticsEmailSettings.subscribed = (response.data.length > 0)
},
function error() {})
}
function populateSubscribedEnginesFromServer(data) {
console.log('data', data)
var subscriptionEngines = []
for (var i = 0; i < data.length; i++) {
var subscription = data[i]
var engine = $scope.engines.filter(function(x) {
if (x.id === subscription.engine) {
var index = $scope.engines.indexOf(x)
$scope.engines[index].type = subscription.type
}
return x.id === subscription.engine
})[0]
console.log('engine', engine)
if (engine) subscription.name = engine.name
subscriptionEngines.push(subscription)
}
console.log('subscriptionEngines', subscriptionEngines)
if (subscriptionEngines.length == 0) {
$scope.analyticsEmailSettings.subscription = 'WeeklyAnalytics'
} else {
$scope.analyticsEmailSettings.subscription = subscriptionEngines[0].type
}
return subscriptionEngines
}
// Save for all always the user have to press the save button if wants save no auto save as it is now
$scope.save = function() {
$scope.loadingAction = true
if ($scope.analyticsEmailSettings.subscribed) {
AnalyticsEmailService.updatesubscriptions($scope.subscriptionEnginesFromServer, function success(response) {}, function error() {})
} else {
$scope.analyticsEmailSettings.subscription = 'WeeklyAnalytics'
$scope.subscriptionEnginesFromServer = []
AnalyticsEmailService.updatesubscriptions($scope.subscriptionEnginesFromServer, function success(response) {}, function error() {})
}
UserSettingsService.save({
userId: $scope.userInfo.id
}, $scope.userInfo, function() {
$scope.loadingAction = false
userConfig.setCurrentUserConfig($scope.userInfo)
userConfig.setUserLocale()
store.set('user', $scope.userInfo)
toaster.pop({
type: 'success',
body: $translate.instant('notifications_user_settings_changed_success')
})
}, function() {})
$scope.subscriptionEngines = []
}
// removeSelectedEngines
getUnselectedEngines = function() {
for (var i = 0; i < $scope.engines.length; i++) {
if ($scope.subscriptionEnginesFromServer.filter(function(x) {
return x.engine === $scope.engines[i].id
}).length == 0)
$scope.engines[i].type = ''
}
}
// #todo: consider referring by array key instead of engineId
function updatesubscriptions(engineId, subscriptionType) {
var engine
for (var i = 0; i < $scope.subscriptionEnginesFromServer.length; i++) {
if ($scope.subscriptionEnginesFromServer[i].engine == engineId) {
engine = $scope.subscriptionEnginesFromServer[i]
}
}
engine.type = subscriptionType
engine.engine = engineId
}
$scope.updateSubscriptionType = function(engine) {
for (var i = 0; i < $scope.subscriptionEnginesFromServer.length; i++) {
updatesubscriptions($scope.subscriptionEnginesFromServer[i].engine, $scope.analyticsEmailSettings.subscription)
}
}
$scope.addSubscribedEngine = function(engine) {
$scope.subscriptionEngines = []
engine.type = $scope.analyticsEmailSettings.subscription
$scope.subscriptionEnginesFromServer.push({
type: engine.type,
engine: engine.id,
name: engine.name
})
}
$scope.selectFirstUnsubscribedEngine = function() {
var filtered
filtered = $scope.engines.filter(function(x) {
return x.type == ''
})
filtered = $filter('orderBy')(filtered, 'name')
$scope.engine.current = filtered.length ? filtered[0] : null
}
$scope.removeSubscribedEngine = function(engine) {
engine.type = ''
for (var i = 0; i < $scope.subscriptionEnginesFromServer.length; i++) {
if ($scope.subscriptionEnginesFromServer[i].engine == engine.id) {
$scope.subscriptionEnginesFromServer.splice(i, 1)
}
}
save()
}
}])
View:
<div ng-controller="UserSettingsCtrl" ng-init="init()">
<div class="content">
<header class="flex-container row header">
<div class="flex-1">
<h1 class="flex-1">{{ 'user_settings_title' | translate }}</h1>
</div>
<!--<a class="logout" href ui-sref="account.settings.changepassword">{{ 'user_change_password_menu' | translate }}</a>-->
</header>
<div class="main-edit">
<div class="subsection">
<div class="inputs-container-row full-width">
<div class="input-group full-width">
<div class="inputfield">
<label class="label ng-binding" for="name">
{{ 'user_settings_firstname_label' | translate }}
</label>
<input type="text" name="firstname" ng-model="userInfo.firstName" class="flex-1" ng-class="{'first-letter-to-upper' : userInfo.firstName.length > 0 }" placeholder="{{ 'user_settings_firstname_placeholder' | translate }}">
</div>
</div>
<div class="input-group full-width">
<div class="inputfield">
<label class="label ng-binding" for="name">
{{ 'user_settings_lastname_label' | translate }}
</label>
<input type="text" name="lastname" ng-model="userInfo.lastName" class="flex-1" ng-class="{'first-letter-to-upper' : userInfo.lastName.length > 0 }" placeholder="{{ 'user_settings_lastname_placeholder' | translate }}">
</div>
</div>
</div>
<div class="inputs-container-row full-width">
<div class="inputs-container-row half-width">
<div class="input-group full-width">
<label class="label" for="name">{{ 'user_settings_language_label' | translate }}</label>
<div class="select-group full-width">
<select class="select" id="selectLanguage" ng-model="userInfo.language" ng-options="key as value for (key , value) in availableLanguages"></select>
<label for="selectLanguage"><span class="fa fa-angle-down"></span></label>
</div>
</div>
</div>
<div class="inputs-container-row half-width">
<div class="input-group full-width">
<label class="label" for="name">
{{ 'user_settings_phone_label' | translate }}
</label>
<input type="text" name="lastname" ng-model="userInfo.phoneNumber" placeholder="{{ 'user_settings_phone_placeholder' | translate }}">
</div>
</div>
</div>
</div>
<div class="subsection">
<div class="inputs-container-row half-width">
<div class="input-group full-width">
<label class="label" for="name">
{{ 'user_settings_password_label' | translate }}
<a ui-sref="account.settings.changepassword" class="button button-link--primary button--first">
{{ 'user_settings_password_button' | translate }}...
</a>
</label>
</div>
</div>
</div>
</div>
<div class="flex-container row header">
<div class="flex-1">
<h1 class="flex-1">{{ 'user_settings_emailStatistics_title' | translate }}</h1>
</div>
</div>
<!--||| Subscribe Start |||-->
<div class="main-edit">
<div class="subsection">
<div class="flex-container row">
<div class="radiobutton-group">
<div class="width-140">
<input id="subscribed" type="checkbox" ng-model="analyticsEmailSettings.subscribed" value="subscribed" class="radiobutton">
<label class="label highlight inline no-bottom-margin" for="subscribed">
{{ 'user_settings_emailStatistics_subscribe' | translate }}
</label>
</div>
</div>
</div>
<div ng-show="analyticsEmailSettings.subscribed">
<div class="flex-container row">
<div class="input-group flex-1" ng-switch="analyticsEmailSettings.subscription">
<label class="label" for="name">{{ 'user_settings_emailStatistics_recurrence' | translate }}</label>
<div class="inputs-container-row half-width" name="oftenReportSent">
<span class="radiobutton flex-1" ng-class="{'checked' : analyticsEmailSettings.subscription === 'WeeklyAnalytics'}" name="radio">
<input type="radio" name="WeeklyAnalytics" ng-model="analyticsEmailSettings.subscription" ng-change="updateSubscriptionType()" ng-checked="analyticsEmailSettings.subscription === 'WeeklyAnalytics'" value="WeeklyAnalytics" id="WeeklyAnalytics" ng-required="">
<label for="WeeklyAnalytics">{{ 'user_settings_emailStatistics_weekly' | translate }}</label>
</span>
<span class="radiobutton flex-1" ng-class="{'checked' : analyticsEmailSettings.subscription === 'MonthlyAnalytics'}">
<input type="radio" name="MonthlyAnalytics" ng-model="analyticsEmailSettings.subscription" ng-change="updateSubscriptionType()" ng-checked="analyticsEmailSettings.subscription === 'MonthlyAnalytics'" value="MonthlyAnalytics" id="MonthlyAnalytics" ng-required="">
<label for="MonthlyAnalytics">{{ 'user_settings_emailStatistics_monthly' | translate }}</label>
</span>
</div>
<div> <span style="color:red;" ng-show="analyticsEmailSettings.subscription == null">Please select option</span></div>
</div>
</div>
<h1>Before</h1>
<div ng-if="engines.length == 1">
<ul class="tags tags--inline item-with-inline-buttons">
<li ng-repeat="engine in engines | orderBy:'name'">
{{engine.name}}
<span class="button-icon button--primary button--delete" ng-click="removeSubscribedEngine(engine); selectFirstUnsubscribedEngine()">
<i class="fa fa-trash-o"></i>
</span>
</li>
</ul>
</div>
<h1>after</h1>
<div ng-show="engines.length > 1">
<div class="flex-container row" ng-show="((engines | filter:{type:''}:true).length != 0)">
<div class="input-group full-width">
<label class="label" for="selectEngine">
{{ 'user_settings_emailStatistics_engines_label' | translate }}:
</label>
<div class="half-width inputfield--horizontal" style="margin-bottom: 10px;">
<div class="full-width select-group" ng-if="(engines | filter:{type:''}:true).length > 0">
<select class="select" id="selectEngine" ng-model="$parent.engine.current" ng-options="website.name for website in engines | filter:{type:''}:true | orderBy:'name'" ng-init="$parent.engine.current = (engines | filter:{type:''}:true | orderBy:'name')[0]">
</select>
<label for="selectSubscription"><span class="fa fa-angle-down"></span></label>
</div>
<span ng-show="engines.length == 1">{{(engines | filter:{type:''}:true)[0].name}}</span>
<div id="btnAddWebSitesSubscription" ng-show="engines.length > 0" class="button button--add" ng-click="addSubscribedEngine(engine.current); selectFirstUnsubscribedEngine()"><i class="fa fa-plus"></i></div>
</div>
</div>
</div>
<div ng-model="successMessage" ng-show="showMessage" style="color:green;" class="message fadein fadeout">{{successMessage}}</div>
</div>
<h1 ng-show="subscriptionEnginesFromServer.length > 0 && engines.length > 1">Websites Subscribed</h1>
<div class="flex-container row" ng-if="subscriptionEnginesFromServer.length > 0 && engines.length > 1">
<ul class="tags tags--inline item-with-inline-buttons">
<li ng-repeat="engine in engines | filter:{type:'Analytics'} | orderBy:'name'">
{{engine.name}}
<span class="button-icon button--primary button--delete" ng-click="removeSubscribedEngine(engine); selectFirstUnsubscribedEngine()">
<i class="fa fa-trash-o"></i>
</span>
</li>
</ul>
</div>
</div>
</div>
<footer class="flex-container flex-end row footer">
<button class="button button--primary button--action" ng-click="save();">
<i ng-show="loadingAction" class="fa fa-spinner fa-spinner-custom"></i>
<span ng-show="!loadingAction">{{ 'general_save' | translate }}</span>
</button>
</footer>
</div>
</div>
Be careful of using ng-hide/ng-show as when the partial is 'hidden' it destroys the model (if there are any) contained within itself (so, use ng-if instead).
In your html in the subscription section, you make a call like this:
ng-change="updateSubscriptionType()"
But in your javascript you have:
$scope.updateSubscriptionType = function(engine) {
for (var i = 0; i < $scope.subscriptionEnginesFromServer.length; i++) {
updatesubscriptions($scope.subscriptionEnginesFromServer[i].engine, $scope.analyticsEmailSettings.subscription)
}
}
So it's expecting an 'engine' argument, which you never pass in. But looking at the code you don't use the engine argument anyway; you use the 'engine' property of $scope.subscriptionEnginesFromServer[i] but that's it.
It however, doesn't do anything that I can see, anyway. It loops through an empty array then calls updatesubscriptions() to do something, but it won't actually call it.
Also, the updatesubscriptions() method itself doesn't actually do anything. This is probably why you're not getting anything in your array. I'd suggest modifying your template slightly, because the subscription radio buttons are outside the engines loop, so you won't be able to associate the subscription type with any engine. Once you have done that, then the subscriptions type radio buttons will have access to 'engine', which you can pass in. Modify your method accordingly:
$scope.updateSubscriptionType = function(engine) {
if (!$scope.subscriptionEnginesFromService.includes(engine)) {
$scope.subscriptionEnginesFromService.push(engine);
}
updatesubscriptions(engine, $scope.analyticsEmailSettings.subscription);
}
And also modify the updatesubscriptions() slightly.
Related
Page looks like this :
HTML
<li class="list-group-item" ng-repeat="eachData in lstRepositoryData">
<div class="ember-view">
<div class="github-connection overflow-hidden shadow-outer-1 br2">
<!-- code to created other stuff-- >
<div class="panel-heading">
<a for="collapse{{$index}} accordion-toggle" data-toggle="collapse" href="#collapse{{$index}}" aria-expanded="true" aria-controls="collapse{{$index}}">Show SFDC
connections</a>
<div id="collapse{{$index}}" class="collapse mt3 panel-collapse">
<div class="row no-gutters pa3">
<div class="col-12 col-sm-6 col-md-8">
<form>
<div class="form-group row">
<label for="inputorgNamel3" class="col-sm-2 col-form-label required">Name</label>
<div class="col-sm-10">
<input type="text" class="form-control" id="inputorgNamel3" placeholder="Name" ng-model="eachData.sfdcOrg.orgName" ng-disabled="eachData.sfdcOrg.disabledForm == 'true'">
</div>
</div>
<div class="form-group row">
<label for="inputenvironment3" class="col-sm-2 col-form-label required">Environment</label>
<div class="col-sm-10">
<div class="dropdown bootstrap-select">
<select class="form-control" id="inputenvironment3" ng-model="eachData.sfdcOrg.environment" ng-disabled="eachData.sfdcOrg.disabledForm == 'true'">
<option value="0" selected>Production/Developer</option>
<option value="1">Sandbox</option>
<option value="2">Custom Org</option>
</select>
</div>
</div>
</div>
<div class="form-group row">
<label for="salesforceLoginl3" class="col-sm-2 col-form-label required">Salesforce Login</label>
<div class="col-sm-10">
<input type="text" class="form-control" id="salesforceLoginl3" placeholder="Salesforce userName"
ng-model="eachData.sfdcOrg.userName" ng-disabled="eachData.sfdcOrg.disabledForm == 'true'">
</div>
</div>
<div class="form-group row" ng-show="eachData.sfdcOrg.environment === '2'">
<label for="salesforceinstanceURLl3" class="col-sm-2 col-form-label required">Instance Url</label>
<div class="col-sm-10">
<input type="text" class="form-control" id="salesforceinstanceURLl3" placeholder="Salesforce Instance Url"
ng-model="eachData.sfdcOrg.instanceURL" ng-disabled="eachData.sfdcOrg.disabledForm == 'true'">
</div>
</div>
<div class="form-group row">
<label for="branchNamel3" class="col-sm-2 col-form-label required">Branch Name</label>
<div class="col-sm-10">
<input class="form-control" id="branchNamel3" placeholder="search branches..."
ng-model="eachData.sfdcOrg.instanceURL">
</div>
</div>
<div class="form-group row">
<div class="form-group">
<!-- Buttons Code -->
</div>
</div>
</form>
</div>
</div>
</div>
</div>
</div>
</div>
</li>
JS Code :
var app = angular.module('forceCIApp', ["angularjs-dropdown-multiselect"]);
app.controller('orderFromController', function ($scope, $http, $attrs) {
$scope.reposInDB = [];
$scope.lstRepositoryData = [];
const sfdcOrg = {
orgName: '',
environment: '0',
userName: '',
instanceURL: '',
authorize: 'Authorize',
save: 'Save',
testConnection: 'Test Connection',
delete: 'Delete',
oauthSuccess: 'false',
oauthFailed: 'false',
oauthSaved: 'false',
disabledForm: 'false',
multiBranchData: [],
multiExtraSettings: {enableSearch: true, showCheckAll: false, showUncheckAll: false},
multiSelectedBranches: []
};
$http.get("/fetchUserName").then(function (response) {
if (response.data !== undefined && response.data !== null) {
$scope.userName = response.data.login;
localStorage.setItem('githubOwner', response.data.login);
$http.get("/fetchRepositoryInDB?gitHubUser=" + response.data.login).then(function (response) {
if (response.data.length > 0) {
for (let i = 0; i < response.data.length; i++) {
let lstBranches = [];
$.each(response.data[i].repository.mapBranches, function (key, value) {
console.log(key);
lstBranches.push(key);
});
sfdcOrg.multiBranchData = changeListToObjectList(lstBranches);
sfdcOrg.multiSelectedBranches = response.data[i].repository.lstSelectedBranches === undefined || null ? [] : changeListToObjectList(response.data[i].repository.lstSelectedBranches);
response.data[i].repository.sfdcOrg = sfdcOrg;
$scope.lstRepositoryData.push(response.data[i].repository);
$scope.reposInDB.push(response.data[i].repository.repositoryFullName);
}
$('#repoConnectedDialog').removeClass('hidden');
}
}, function (error) {
});
const avatarSpanTag = '<span class="absolute flex items-center justify-center w2 h2 z-2 ' +
'nudge-right--4 pe-none" style="top: -15px">\n' +
' <img src=' + response.data.avatar_url + '>\n' +
' </span>';
$(avatarSpanTag).insertAfter('#idSelectTab');
}
}, function (error) {
});
When I start editing input fields other divs input field also gets changed. But the data is different in both divs eachData.
Also disabling the form with eachData.sfdcOrg.disabledForm works fine.
But modifying the input elements modifies all the the input fields.
How do I avoid this?
The data was constructed by reference assignment instead of creating a clone object for each sfdcOrg property of each item in the lstRepositoryData array.
$http.get("/fetchRepositoryInDB?gitHubUser=" + response.data.login).then(function (response) {
if (response.data.length > 0) {
for (let i = 0; i < response.data.length; i++) {
let lstBranches = [];
$.each(response.data[i].repository.mapBranches, function (key, value) {
console.log(key);
lstBranches.push(key);
});
sfdcOrg.multiBranchData = changeListToObjectList(lstBranches);
sfdcOrg.multiSelectedBranches = response.data[i].repository.lstSelectedBranches === undefined || null ? [] : changeListToObjectList(response.data[i].repository.lstSelectedBranches);
̶r̶e̶s̶p̶o̶n̶s̶e̶.̶d̶a̶t̶a̶[̶i̶]̶.̶r̶e̶p̶o̶s̶i̶t̶o̶r̶y̶.̶s̶f̶d̶c̶O̶r̶g̶ ̶=̶ ̶s̶f̶d̶c̶O̶r̶g̶;̶
response.data[i].repository.sfdcOrg = angular.copy(sfdcOrg);
$scope.lstRepositoryData.push(response.data[i].repository);
$scope.reposInDB.push(response.data[i].repository.repositoryFullName);
}
$('#repoConnectedDialog').removeClass('hidden');
}
});
Use angular.copy to clone a new object.
I have a form for editing data.In it there is some checkboxes. I get the previously selected checked box array[] from the DB I want to checked those check boxes as checked in the edit profile form. When we editing the page.
app.component.html file:
<form [formGroup]="editCategoryForm" >
<div class="form-group">
<mat-form-field>
<input matInput placeholder="Name" formControlName="name" >
</mat-form-field>
</div>
<div formArrayName="categoryArray" >
<fieldset *ngFor="let address of editCategoryForm.controls.categoryArray['controls']; let i = index" >
<div [formGroupName]="i" >
<div class="form-group">
<mat-form-field>
<input matInput placeholder="Label" formControlName ="label" required>
</mat-form-field>
<br/>
<div class="check-box" *ngFor="let data of measurementData">
<input type="checkbox" (change)="onChange(i,data._id,data.name, $event.target.checked)" > {{data.name}}
</div>
<div class="col-sm-1">
<button mat-mini-fab color="warn" *ngIf="editCategoryForm.controls.categoryArray['controls'].length > 1" title="Remove Fields" (click)="removeLair(i)">x</button>
</div>
</div>
</div>
</fieldset>
<br/>
<div class="form-group">
<button mat-raised-button color="accent" (click)="addNew()">Add Measurement</button>
</div>
<div class="form-group">
<button style="float: right;margin: 29px;" mat-raised-button color="primary" (click)="submitdata()">Submit</button>
</div>
</div>
</form>
I have this for capturing the array of measurements. that are in the DB:
this.category = {
"_id":"5c4b0d6918f72032c0569004",
"name":"categorytest",
"measurements": [{
"measurements": [
{"name":"Chest","id":"5c4ac1c4da2dfe251aeee037"},
{"name":"Stomach","id":"5c4ac1d6da2dfe251aeee038"},
{"name":"Hip","id":"5c4ac1dbda2dfe251aeee039"},
{"name":"Length","id":"5c4ac201da2dfe251aeee03c"}
],
"label":"testfff"
},
{
"measurements":[{"name":"Chest","id":"5c4ac1c4da2dfe251aeee037"}],
"label":"httt"
}]
}
app.component.ts File:
this.https.post<any>('api/category/details', data).subscribe(response => {
this.category = response.category;
this.editCategoryForm.controls['name'].setValue(this.category.name);
console.log(this.category);
console.log(this.category.measurements.length);
for (let i = 0; i < this.category.measurements.length; i++) {
if (i !== 0) {
const control = <FormArray>this.editCategoryForm.controls['categoryArray'];
control.push(this.getData());
}
this.categoryArray.at(i).get('label').setValue(this.category.measurements[i].label);
}
});
Here is a Stackblitz demo.
inputChecked(i,data){
let checked = false;
//console.log(this.category.measurements[i].measurements);
//console.log('data = ', data);
for (let l = 0; l < this.category.measurements[i].measurements.length; l++){
let temp = this.category.measurements[i].measurements[l];
//console.log('inside =',temp);
if (temp.name == data.name && temp.id == data._id){
checked = true; }
}
return checked;
}
put the above in your ts file, then reference it like so in your html file:
<input type="checkbox" (change)="onChange(i,data._id,data.name, $event.target.checked)" [checked]="inputChecked(i,data)"> {{data.name}}
I completed the contact-manager tut from Aurelia.io and am incorporating it into as task manager tut I'm putting together. The markup below sets the li class based on task.id === $parent.id.
task-list.html
<template>
<div class="task-list">
<ul class="list-group">
<li repeat.for="task of tasks" class="list-group-item ${task.id === $parent.selectedId ? 'active' : ''}">
<a route-href="route: tasks; params.bind: {id:task.id}" click.delegate="$parent.select(task)">
<h4 class="list-group-item-heading">${task.name}</h4>
<span class="list-group-item-text ">${task.due | dateFormat}</span>
<p class="list-group-item-text">${task.isCompleted}</p>
</a>
</li>
</ul>
</div>
task-list.js
#inject(WebAPI, EventAggregator)
export class TaskList {
constructor(api, ea) {
this.api = api;
this.tasks = [];
ea.subscribe(TaskViewed, x => this.select(x.task));
ea.subscribe(TaskUpdated, x => {
let id = x.task.id;
let task = this.tasks.find(x => x.id == id);
Object.assign(task, x.task);
});
}
created() {
this.api.getList().then( x => this.tasks = x);
}
select(task) {
this.selectedId = task.id;
return true;
}
}
If I edit the current task, represented by
task-detail.html
<template>
<require from="resources/attributes/DatePicker"></require>
<div class="panel panel-primary">
<div class="panel-heading">
<h3 class="panel-title">Edit Task Profile</h3>
</div>
<div class="panel-body">
<form role="form" class="form-horizontal">
<div class="form-group">
<label class="col-sm-2 control-label">Name</label>
<div class="col-sm-10">
<input type="text" placeholder="name" class="form-control" value.bind="task.name">
</div>
</div>
<div class="form-group">
<label class="col-sm-2 control-label">Description</label>
<div class="col-sm-10">
<input type="text" placeholder="description" class="form-control" value.bind="task.description">
</div>
</div>
<div class="form-group">
<label class="col-sm-2 control-label">Due Date</label>
<div class="col-sm-10">
<div class="input-group date">
<input type="text" datepicker class="form-control" value.bind="task.due | dateFormat:'L'"><span class="input-group-addon"><i class="glyphicon glyphicon-th"></i></span>
</div>
</div>
</div>
<div class="form-group">
<label class="col-sm-2 control-label">Urgency</label>
<div class="col-sm-10">
<input type="range" min="1" max="5" step="1" class="form-control" value.bind="task.urgency">
</div>
</div>
</form>
</div>
</div>
<div class="button-bar">
<button class="btn btn-info" click.delegate="addTask(task)" >Add New</button>
<button class="btn btn-success" click.delegate="save()" disabled.bind="!canSave">Save Edit</button>
</div>
</template>
task-detail.js
#inject(WebAPI, EventAggregator, Utils, DialogService)
export class TaskDetail {
constructor(api, ea, utils, dialogService) {
this.api = api;
this.ea = ea;
this.utils = utils;
this.dialogService = dialogService;
}
activate(params, routeConfig) {
this.routeConfig = routeConfig;
return this.api.getTaskDetails(params.id).then(task => {
this.task = task;
this.routeConfig.navModel.setTitle(task.name);
this.originalTask = this.utils.copyObj(task);
this.ea.publish(new TaskViewed(task));
});
}
get canSave() {
return this.task.name && !this.api.isRequesting;
}
save() {
console.log(this.task);
this.api.saveTask(this.task).then(task => {
this.task = task;
this.routeConfig.navModel.setTitle(task.name);
this.originalTask = this.utils.copyObj(task);
this.ea.publish(new TaskUpdated(this.task));
});
}
canDeactivate() {
if (!this.utils.objEq(this.originalTask, this.task)) {
let result = confirm('You have unsaved changes. Are you sure you wish to leave?');
if (!result) {
this.ea.publish(new TaskViewed(this.task));
}
return result;
}
return true;
}
addTask(task) {
var original = this.utils.copyObj(task);
this.dialogService.open({viewModel: AddTask, model: this.utils.copyObj(this.task)})
.then(result => {
if (result.wasCancelled) {
this.task.name = original.title;
this.task.description = original.description;
}
});
}
}
If a value has changed, navigation away from the current task is not allowed, and that works -- that is, the contact-detail part of the UI doesn't change. However, the task <li>, that one tries to navigate to still gets the active class applied. That's not supposed to happen.
If I step along in dev tools, on the Aurelia.io contact-manager, I see that the active class is briefly applied to the list item, then it goes away.
from the contact-manager's contact-list.js This was run when clicking an <li> and no prior item selected.
select(contact) {
this.selectedId = contact.id;
console.log(contact);
return true;
}
This logs
Object {__observers__: Object}
Object {id: 2, firstName: "Clive", lastName: "Lewis", email: "lewis#inklings.com", phoneNumber: "867-5309"}
The same code on my task-manager's (obviously with "contact" replaced by task") task-list.js logs
Object {description: "Meeting With The Bobs", urgency: "5", __observers__: Object}
Object {id: 2, name: "Meeting", description: "Meeting With The Bobs", due: "2016-09-27T22:30:00.000Z", isCompleted: false…}
My first instinct is to say it's got something to do with this.selectedId = contact.id
this there would refer to what I assume is a function called select (looks like the function keyword is missing in your example?) or the global object (i.e. window)
select(contact) {
this.selectedId = contact.id;
console.log(contact);
return true;
}
Fixed it. It wasn't working because I had pushstate enabled. That clears things up. Thanks therealklanni.
In the dynamic input field is there any option to implement plusSign = true only for the last item ?
(function() {
var app = angular.module('managementApp', []);
// var app = angular.module('managementApp', ['ngRoute']);
app.controller('phonebookController', function($scope, $http) {
$scope.dynamicField = function(buttonStatus, inputIndex) {
if (!buttonStatus) {
$scope.currentContact.contacts.push({
"phone": ""
});
} else {
$scope.currentContact.contacts.splice(inputIndex, 1);
}
};
$scope.currentContact = [{
"phone": "07875 506 426"
}, {
"phone": "+91 9895 319991"
}, {
"phone": "+44 7875 506 426"
}];
$scope.dynamicField = function(buttonStatus, inputIndex) {
if (!buttonStatus) {
$scope.currentContact.push({
"phone": ""
});
} else {
$scope.currentContact.splice(inputIndex, 1);
}
};
$scope.checkIndex = function(totalCount, indexCount) {
indexCount++;
// alert(indexCount);
/*if (totalCount === indexCount) {
//alert("last one");
$scope.plusSign = true;
}else{
$scope.plusSign = false;
}*/
};
});
})();
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.4/css/bootstrap.min.css" rel="stylesheet" />
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div class="container" ng-app="managementApp">
<div class="row" ng-controller="phonebookController">
<div class="form-group" ng-repeat="contact in currentContact" ng-init="checkIndex(currentContact.length, $index);">
<label for="contact-number3" class="col-sm-3 control-label">Contact number {{$index + 1 }}</label>
<div class="col-sm-9">
<div class="input-group">
<input type="tel" class="form-control" placeholder="Contact number {{$index + 1 }}" ng-model="contact.phone">
<span class="input-group-btn">
<button class="btn btn-default" type="button" ng-init="plusSign = true"
ng-click="plusSign = !plusSign; dynamicField(plusSign, $index);">
<i class="glyphicon " ng-class="plusSign ? 'glyphicon-plus' : 'glyphicon-minus'"></i>
</button>
</span>
</div>
</div>
</div>
</div>
</div>
You can use $last inside ng-repeat which is true if the repeated element is last in the iterator. Or you can do it with css only with .row:last-of-type {/**/}.
check $last in your function for example:-
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.4/css/bootstrap.min.css" rel="stylesheet" />
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div class="container" ng-app="managementApp">
<div class="row" ng-controller="phonebookController">
<div class="form-group" ng-repeat="contact in currentContact" ng-init="checkIndex($last);">
<label for="contact-number3" class="col-sm-3 control-label">Contact number {{$index + 1 }}</label>
<div class="col-sm-9">
<div class="input-group">
<input type="tel" class="form-control" placeholder="Contact number {{$index + 1 }}" ng-model="contact.phone">
<span class="input-group-btn">
<button class="btn btn-default" type="button" ng-init="plusSign = true"
ng-click="plusSign = !plusSign; dynamicField(plusSign, $index);">
<i class="glyphicon " ng-class="plusSign ? 'glyphicon-plus' : 'glyphicon-minus'"></i>
</button>
</span>
</div>
</div>
</div>
</div>
</div>
controller method
$scope.checkIndex = function(last) {
(last === true)
$scope.plusSign = true;
else
$scope.plusSign = false;
};
I need to add HTML content on Button Click event using AngularJS. Is it possible??
My index.html
<div class="form-group">
<label for="category"> How Many Questions Want You Add ? </label>
<div class="col-sm-10">
<input type="text" class="form-control input-mini" id="questionNos" name="questionNos" placeholder="Nos." ng-model="myData.questionNos">
<div class="input-append">
<button class="btn-warning btn-mini" type="button" ng-click="myData.doClick()">Generate</button>
</div>
</div>
</div>
I want to add Nos. of HTML divs as per quantity added dynamically..
myApp.js
angular.module("myApp", []).controller("AddQuestionsController",
function($scope) {
$scope.myData = {};
$scope.myData.questionNos = "";
$scope.myData.doClick = function() {
//Do Something...????
};
});
It should be possible. I would data-bind your Divs to viewModel elements, and in your doClick function create the viewModels.
I would avoid directly creating Html in your viewModel.
For example:
<div class="form-group">
<label for="category"> How Many Questions Want You Add ? </label>
<div class="col-sm-10">
<input type="text" class="form-control input-mini" id="questionNos" name="questionNos" placeholder="Nos." ng-model="myData.questionNos">
<div class="input-append">
<button class="btn-warning btn-mini" type="button" ng-click="myData.doClick()">Generate</button>
</div>
<div ng-repeat="q in myData.questions">
<!-- BIND TO Q HERE -->
</div>
</div>
</div>
And in doClick:
$scope.myData.doClick = function() {
var newQuestions = getNewQuestionViewModels($scope.myData.questionNos);
for (var i = 0; i < newQuestions.length; i++) {
$scope.myData.questions.push(newQuestions[i]);
}
};
You have to store questions in collection and do repeat.
DEMO
HTML:
<div>
<input type="text" ng-model="data.qcount">
<button type="button" ng-click="data.add()">Add</button>
</div>
<div>
<div ng-repeat="q in data.questions track by $index">
<pre>{{ q | json }}</pre>
</div>
</div>
JS:
$scope.data = {
questions: [],
qcount: 0,
add: function() {
var dummy = {
'title': 'Q title',
'body': 'Q body'
},
newQ = [];
for (var i = 0; i < $scope.data.qcount; ++i) {
newQ.push(dummy);
}
$scope.data.questions = $scope.data.questions.concat(newQ);
$scope.data.qcount = 0;
}
};