Marc Rasmussen
Marc Rasmussen

Reputation: 20565

Angular altering individual value changes value globally

I wasnt quite sure what to call this question but here is my problem:

I have the following array:

    $scope.competenceArray =[];

This array contains the following object from:

var competence = {competence_type_id: type_id, id: id ,name: "name", organization_id: organization_id};

It contains more or less 50 types of this object.

Then i have another array:

    $scope.jobprofiles = [];

This array contains many of the following object:

    $scope.jobprofile = {name: name, selectedCompetence: [competence]};

So each jobprofile has a name value and an array of competence

So far so good.

Then i have the following select:

<div class="form-group">
<label>Vælg kompetencer</label>
<ui-select multiple ng-model="jobprofile.selectedCompetence" theme="bootstrap"
           ng-disabled="disabled">
    <ui-select-match placeholder="Vælg kompetencer">{{$item.name}} &lt;{{$item.competence_type_id ==
        1 ? 'Faglig' : 'Personlig' }}&gt;</ui-select-match>
    <ui-select-choices group-by="someGroupFn"
                       repeat="competence in competenceArray | propsFilter: {name: $select.search, competence_type_id: $select.search}">
        <div ng-bind-html="competence.name | highlight: $select.search"></div>
        <small>
            {{competence.competence_type_id == 1 ? 'Faglig' : 'Personlig'}}
        </small>
    </ui-select-choices>
</ui-select>

Basicly this this allows me to add multiple competence objects into my jobprofile.selectedCompetence

Once done i add these to an editable table:

                    <table class="table table-bordered table-hover table-condensed bg-white-only">
                    <tr style="font-weight: bold">
                        <td style="width:35%">Navn</td>
                        <td style="width:20%">Forventet niveau</td>
                        <td style="width:25%">Ret</td>
                    </tr>
                    <tr ng-repeat="selectCompetence in row.selectedCompetence">
                        <td class="v-middle">
                            <!-- editable username (text with validation) -->
<span editable-select="selectCompetence.name" e-name="name" e-ng-options="s.name as s.name for s in competenceArray" e-form="rowform" onbeforesave="checkName($data, user.id)"
      e-required>
  {{ selectCompetence.name || 'empty' }}
</span>
                        </td>
                        <td class="v-middle">
                            <!-- editable status (select-local) -->
<span editable-select="selectCompetence.level" e-name="level" e-form="rowform"
      e-ng-options="level.level_id as level.level_id for level in levelsArray">
  {{ selectCompetence.level  }}
</span>
                        </td>
                        <td style="white-space: nowrap">
                            <!-- form -->
                            <form editable-form name="rowform" onbeforesave="saveUser($data, user.id)"
                                  ng-show="rowform.$visible" class="form-buttons form-inline"
                                  shown="inserted == user">
                                <button type="submit" ng-disabled="rowform.$waiting"
                                        class="btn btn-sm btn-info">
                                    save
                                </button>
                                <button type="button" ng-disabled="rowform.$waiting"
                                        ng-click="rowform.$cancel()" class="btn btn-sm btn-default">
                                    cancel
                                </button>
                            </form>
                            <div class="buttons" ng-show="!rowform.$visible">
                                <button class="btn btn-sm btn-info" ng-click="rowform.$show()"><i class="fa fa-edit"></i></button>
                                <button class="btn btn-sm btn-danger" ng-click="removeCompetence(row,$index)"><i class="fa fa-times"></i></button>
                            </div>
                        </td>
                    </tr>
                </table>

First i loop through all of the jobprofile in the jobprofiles array

Then for each of the individual jobprofile i loop through their array of competence

<tr ng-repeat="selectCompetence in row.selectedCompetence">

This works fine and without a problem however something strange then happens:

What you need to note is the following line of code:

<td class="v-middle">
    <span editable-select="selectCompetence.level" e-name="level" e-form="rowform"
          e-ng-options="level.level_id as level.level_id for level in levelsArray">
      {{ selectCompetence.level  }}
    </span>

Here i am able to edit the level of each of the selectedCompetence using the following array:

    $scope.levelsArray = [
        {level_id: 1},
        {level_id: 2},
        {level_id: 3},
        {level_id: 4},
        {level_id: 5},
        {level_id: 6},
        {level_id: 7},
        {level_id: 9},
        {level_id: 9},
        {level_id: 10}
    ];

now to the actual problem.

when i add the value level to a selectedCompetence it automaticly adds the value to the object in the competenceArray. i debugged and found out it might be because they have the same hash value. But can anyone tell me how i can avoid this?

Upvotes: 0

Views: 49

Answers (2)

maurycy
maurycy

Reputation: 8465

from what I can see you are passing object by reference so you actually work on same object, to avoid it you will need to create a copy while passing either by

angular.copy(obj)

or

Object.create(obj)

Upvotes: 1

Ed_
Ed_

Reputation: 19138

Objects in javascript are passed by reference. As such, when you add a competence to a Job, you've actually got a reference to the same object that is in the competence array.

My approach would be either:

  1. Use angular.copy to copy the whole object into the job's own competence array, and then edit them.

  2. Create an object with keys that correspond to a competence id, and values that correspond to a competence level id.

Upvotes: 0

Related Questions